Tomas' place in cyberspacehttp://www.härdin.se/2024-01-07T21:18:34+01:002023 moose hunt report2024-01-07T21:18:34+01:002024-01-07T21:18:34+01:00tomastag:www.härdin.se,2024-01-07:/blog/2024/01/07/2023-moose-hunt-report/<p>Last year I participated in my first ever moose hunt.
This post documents my experience of it.
Being a huge nerd I have also collected some statistics around it as a labour process.</p>
<p>For readers who are unaware, the moose hunt in Sweden is something nearly religious.
Life in rural …</p><p>Last year I participated in my first ever moose hunt.
This post documents my experience of it.
Being a huge nerd I have also collected some statistics around it as a labour process.</p>
<p>For readers who are unaware, the moose hunt in Sweden is something nearly religious.
Life in rural Sweden largely revolves around it, and the year for many is divided into before, during and after the hunt.
Entire sections of Swedish society shuts down, especially during its first weekend.
For example the surgery ward in Sundsvall shut down a couple of years ago because all the surgeons were out hunting.</p>
<p>Oh and a warning to sensitive readers: there will be dead animals, but I'll keep the bloodiest parts out.</p>
<p><a href="http://www.härdin.se/images/jakt/skalle.jpg"><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/jakt/tskalle.jpg" alt="Moose skull" title="Metal album cover?"/></a></p>
<h2>Background</h2>
<p>I have a summer house since a couple of years back.
Because it is outside city limits (detaljplanerat område), this both entitles and obliges me to take care of the large game on it (viltvård).
Up here that means moose and bears.
To this end I signed an emphyteusis contract (arrende) with a local hunting team a while back, letting them take care of it for me, which is a standard arrangement up here.</p>
<p>In late 2022 I noticed ABF (the Workers' Educational Association) was holding a hunting course here in Umeå.
I'd already gotten more curious about flora, having done calculations around and attending seminars on sustainable logging, and also writing about BECCS here on the blog (<a href="http://www.härdin.se/blog/2022/06/20/gobigas-technical-coefficients/">GoBiGas technical coefficients</a>).
Given that, but not having a good grasp on fauna and also holding hunting land, this struck me as an excellent thing to enroll in.
Also shooting is fun.
I enrolled around November 2022, and by May 2023 I had passed the theory exam.
In Sweden hunting theory covers a lot, and the exam is particularly difficult.
60 out of 70 questions must be answered correctly.
As soon as the snow cleared the shooting exam was also swiftly taken care of - turns out I'm a decent shot!</p>
<p>During all this I got in contact with the leader of the hunting team, who was happy to accept a new (trial) member.</p>
<h2>How moose hunting works</h2>
<p>Most moose hunting in Sweden works like this:
an area is chosen, typically many hundreds of hectares in size.
Stationary shooters are positioned around the area, either in stands or on the ground.</p>
<div style="text-align:center">
<a href="http://www.härdin.se/images/jakt/IMG_20230917_162323.jpg"><img style="width:25%;" src="http://www.härdin.se/images/jakt/tIMG_20230917_162323.jpg" alt="My hunting stand" title="The pinnacle of Västerbottnian engineering"/></a> <a href="http://www.härdin.se/images/jakt/IMG_20230917_122139.jpg"><img style="width:50%" src="http://www.härdin.se/images/jakt/tIMG_20230917_122139.jpg" alt="A hunting spot in a shallow pit in the ground" title="This spot is the pits"/></a></div>
<p>Above left is a picture of the stand on my property.
It's outfitted with an antenna for better radio coverage, and padding on the seat for maximum comfort.
The tarp makes it moderately wind proof.
The picture on the right is another spot, a shallow pit in the ground.</p>
<p>Once the shooters are in position, dog teams are sent in to locate and to try and get the moose moving towards the shooters.
The dog teams often have shooters of their own, who tend to fell the plurality of animals.
VHF radios are used to coordinate things.
The dogs and their handlers typically have GPS trackers and associeted phone apps, which sadly are proprietary software.</p>
<p>Once felled, the animal is field dressed and a "moose puller" (combitrac, a kind of tracked sled) is used to pull the animal out of the woods onto a trailer.
The animal can then be taken to a slaughtering hut and processed further.
Animals typically aren't quartered in the field, which I hear is the norm in North America.</p>
<h2>Preparations</h2>
<p>Preparations included one half day of maintenance with the entire team splitting up into groups and fixing the hunting stands among other things.
I was assigned to the cleaning crew this year, so another half day of cleaning the butchering tools was also done.
Not too laborious.</p>
<h2>The first weekend</h2>
<p>I already had the notion that the first hunting weekend is quite hectic.
It turned out to be even moreso than I had anticipated.
The hunt started on Friday the 1st of September.
"In position at 06:00" meant waking up at 05:00.
Luckily I was assigned to the stand on my property, so I did not have to do much more than make breakfast, brew coffee, pack sandwiches and walk with my gear to the stand.
Subsequent days I would pre-load the coffee maker and make sandwiches the evening before.</p>
<p>Getting into position means climbing into the stand, unpacking the map, radio, coffee and snacks, as well as loading and safing the rifle. For those wondering: a Carl-Gustaf ("Swedish Mauser") in 6.5x55 mm Swedish.
Then begins the main task: waiting.
Waiting and listening and watching.</p>
<p><a href="http://www.härdin.se/images/jakt/IMG_20230901_073420.jpg"><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/jakt/tIMG_20230901_073420.jpg" alt="View from my stand" title="I have since cut down a lot of the brush hindering the view"/></a></p>
<p>One unfortunate thing during this very first "shift" is that I had the wrong frequency programmed on my radio.
Apparently there was a bull moose very close to my position, but I was not able to hear the heads-up over the radio, and the sneaky mister evaded my senses.</p>
<p>At around 11:00 there was a break.
One bull and one calf down.
Meetup at the butchering hut.
The calf had already been processed when I got there, and since recovering the bull was taking some time, most people present ate lunch.</p>
<p><a href="http://www.härdin.se/images/jakt/IMG_20230901_123728.jpg"><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/jakt/tIMG_20230901_123728.jpg" alt="Bull moose on combitrac" title="Tastefully cropped out: the emasculation in progress"/></a></p>
<p>When he arrived, the bull was winched by the hind legs and hung by the equivalent of the gaskins on a horse.
The main task was to flay, gut and quarter the field dressed carcass.
Being new, I observed the flaying.
Noticing my interest, I was instructed by a team member how to do it, and joined in.
Once enough of the hide had been liberated, the winch and two metal "claws" were used to grip the hide and pull the rest of it off like a sweater.
The head and hide were removed and the hide salted for sale to tanners.
The remaining guts were removed and a reciprocating saw was used to cut the carcass in half along the spine,
which is about as nasty as it sounds.
Each half was then hung on hooks and halved again into front and hind quarters.
The quarters were further processed and finally put into a walk-in fridge to hang until Thursday.
This is important for tenderness.
All in all the process described above took maybe 1-1½ hours.</p>
<p>After this some Cameroonian forest guest workers showed up to pick through the bits destined for the offal tip.
The priest in our team assisted in extracting the tongues and cheeks from the moose heads, which our guests happily accepted.
I am not sure what organs they took, but next year I'll be sure to warn against taking livers from adult animals due to risk of fallout from Chernobyl, and other toxins that tend to accumulate in old livers.
Later on I took a calf liver for myself, and next year I'll probably snag a tongue.</p>
<p>Around 13:00 everyone headed out into the field again.
My radio was correctly programmed this time.
A second bull was felled and we headed back to the hut around 17:00.</p>
<p><a href="http://www.härdin.se/images/jakt/IMG_20230901_172817.jpg"><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/jakt/tIMG_20230901_172817.jpg" alt="Bull moose on combitrac and with tongue lolling out" title="}:P"/></a></p>
<p>This bull too was processed.
After this we in the cleaning crew still had cleaning to do.
When everything was said and done the time was 19:30.
Twenty people had been going at it for thirteen and a half hours.
I went home, ate dinner, prepared sandwiches for the next day and promptly collapsed in bed.
No shower because my water heater decided this was a good time to break.</p>
<p>The second day was similar to the first day, but luckily ended around 18:00.
Two bulls felled.
The third day ended up a half day.
One heifer, one bull.
The walk-in fridge was now full and all that remained was to wait until Thursday.
On Monday I borrowed my neighbors' shower and washed off three days' worth of stink.
Celebratory beers were had.</p>
<h2>Butchering</h2>
<p>The meat that makes up each team member's lot was processed the Thursday after the hunt.
5-6 people took care of separating the large pieces into cuts.
The rest, me included, were on polishing duty for the pieces that were going to be turned into mince.
This involves cutting away excess fat and connective tissue.</p>
<p><a href="http://www.härdin.se/images/jakt/IMG_20230907_122053.jpg"><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/jakt/tIMG_20230907_122053.jpg" alt="Hundreds of kg of moose meat on plastic covered tables and in plastic tubs" title="Should be enough meat for about a week"/></a></p>
<p>All in all everyone got around 25 kg of cuts and a bit over 13 kg of mince.
I heard the number 800 kg in total.
What I had not planned for was that I had to further cut the pieces up for freezing.
For some reason I had assumed everyone would be getting portion pieces vacuum sealed or something.
Not so!
So in addition to six hours of butchering, the rest of the evening was spent splitting the cuts into portions and similarly with the mince,
labelling and finally putting everything into my freezers.
By 23:00 or so I was finished.</p>
<h2>Subsequent weekends</h2>
<p>The weekends after the first one were far less taxing, and there is less expectations on attending.
Attending means getting points towards half calves, which are handed out in a round robin fashion to those who have attended ten shifts.
Any adults felled on subsequent weekends were sold flayed and quartered to a butcher, bringing money into the team.</p>
<p><a href="http://www.härdin.se/images/jakt/IMG_20230916_114023.jpg"><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/jakt/tIMG_20230916_114023.jpg" alt="Dog with moose foreleg and a sock around his left hind paw" title="Poor fella. A least he has a hoof to munch on"/></a></p>
<p>Above is one of our dogs enjoying a cut-off foreleg.
He'd lost one of his claws in the woods and so was out of commission for the rest of the hunt.</p>
<p>September 23rd was the end of the first part of the hunt. Eight days hunting plus one day butchering up to this point.
Everyone enjoyed a two week break before resuming.</p>
<p><a href="http://www.härdin.se/images/jakt/IMG_20231021_082752.jpg"><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/jakt/tIMG_20231021_082752.jpg" alt="View from my stand in late October. Sun is low on the horizon. Frost on the ground" title="Getting darker and colder..."/></a></p>
<p>My notes on the October hunt are sparse, but it involved two weekends before weather caused another pause.
This because morning frost would risk hurting our dogs' pawsies.
Eventually it got cold enough that I had to use a kerosene stove to keep warm in the field.</p>
<p>Another attempt was made on November 3rd after sufficient (but not too much!) snow had fallen.
I was not able to attend, and turnout was only seven people.
No animals felled.</p>
<p>A final attempt was made on the 25th of November on skis, which I was also not able to attend.
Based on the lack of any SMS to the contrary, I assume no animals were felled here either, especially since dogs were not an options.</p>
<h2>Closing thoughts</h2>
<p>I've learned a lot from all this.
Much like getting my amateur radio license has lead me to notice antennas everywhere,
getting a hunting license means I take note of wild animals much more than I used to.
Reproduction cycles, migratory patterns, what kind of fowl lives in the area, tracks in the ground..</p>
<p>Because I do not eat much meat, I now have more of it than I suspect I'll be able to eat in a year.
But that is less of a problem as I have plenty of friends who are interested in buying meat from me.
I also tend to bring moose meat to dinners with friends or family, which has so far been greatly appreciated!</p>
<p>I did not see any moose at all during the hunt, but it was close several times.
Therefore I did not fell any moose yet.
Time will tell whether I have it in me to kill.</p>
<p>I have plenty of friends who are vegetarian or even vegan.
The reactions from them have so far been mixed, ranging from "you are psychopathic!" to "well, someone has to do it".
The former camp are usually not willing to discuss game politics, nor confront whether it is better for the game that death comes as a surprise, or if it is better that they are taken by wolves or bears where death comes.. not as a surprise.
There is also the issue that while predators don't really attack people, they do attack dogs, horses and livestock.
And they of course compete for game.
Without predation or hunting, the moose and deer population would explode, causing problems for forestry, agriculture and causing even more traffic accidents.</p>
<p>Another factor is the logging companies, who would prefer that the moose were eradicated.
This because moose love grazing on young spruce and pine, which hurts profits.
Such excessive culling is not popular with the hunting corps, nor with conservationists.
One example in the news is the Finnish forest company Stora Enso telling the hunters on a section of their land to fell 152 animals rather than the 52 allotted by the authorities (<a href="https://www.svt.se/nyheter/lokalt/orebro/algjakten-jagarforbundet-rasar-mot-stora-enso-de-skiter-i-myndighetsbeslut">Jägareförbundet rasar mot Stora Enso inför älgjakten: ”En absurd historia”</a>).
This has led to some hunters in the area boycotting the hunt (<a href="https://www.svt.se/nyheter/lokalt/dalarna/jagareforbundet-i-dalarna-uppmanar-till-bojkott-av-fortsatt-algjakt--phjaf9">Jägareförbundet i Dalarna uppmanar till bojkott av fortsatt älgjakt</a>).
Despite this 74 animals were still felled, and the authorities appear to be powerless to do anything (<a href="https://www.svt.se/nyheter/lokalt/orebro/fler-algar-an-beslutat-fallda-runt-hallefors-lansstyrelsen-i-orebro-forsokte-avbryta-jakten--goa7vs">Fler älgar än beslutat fällda runt Hällefors – länsstyrelsen i Örebro försökte avbryta jakten</a>).</p>
<h2>Numbers</h2>
<p>The numbers below are counted on the team as a whole, 19 people. We had one guest during the first weekend, making 20 in total unless I missed some.
The area covered is 4000 hectares.</p>
<p>Preparations: 92 hours<br/>
First weekend: 590 hours (lunches subtracted)<br/>
Butchering: 118 hours<br/>
Subsequent weekends: 747½ hours<br/>
Yield: about 800 kg of meat (cuts and mince) plus bones<br/>
Time per kg of meat: 1h56min</p>
<p>Call it an even two hours per kg. This does not include the time people spend the rest of the year putting up salt licks, putting out winter feed, tending to camera traps and so on.</p>
<p>There are many tools that could greatly reduce the hours listed above, such as drones and thermal cameras.
Such tools are currently illegal when hunting moose.
Initially I thought these rules silly, but having realized that the logging companies would love it if they could use drones with thermal cameras to kill all moose on their land, perhaps these rules aren't so bad.</p>
<p>If land was held in common and if the profit motive was not front and center, the situation would be very different.
Much larger hunting teams might be formed, benefitting from economics of scale; the area covered by stationary shooters is quadratic in the number of shooters.
Fewer moose would slip past as they do at present, and the limiting factor would be dogs.
Some readers might think "well why don't you just do that now then?", but the problem is the logging companies that own vast tracts of land up here in Norrland.
It is very difficult to form large patches of nicely shaped land (välarronderad mark) that doesn't include too much land owned by these companies.
As a result, teams become smaller and hunting labour-power is used inefficiently.
Private property puts fetters on this aspect of production, just like all others.</p>FmiGo ported to Debian 12 and Ubuntu 23.102023-11-03T17:54:00+01:002023-11-03T17:54:00+01:00tomastag:www.härdin.se,2023-11-03:/blog/2023/11/03/fmigo-ported-to-debian-12-and-ubuntu-23-10/<p>Yesterday I finally got around to adding support for <a href="https://www.debian.org/releases/bookworm/">Debian 12 (Bookworm)</a> and <a href="https://releases.ubuntu.com/mantic/">Ubuntu 23.10 (Mantic Minotaur)</a> to <a href="https://www.fmigo.net/">FmiGo</a>.
A bug that caused one test to hang put me off doing this for a while.
After a bunch of <code>printf()</code> debugging the bug turned out to be some kind …</p><p>Yesterday I finally got around to adding support for <a href="https://www.debian.org/releases/bookworm/">Debian 12 (Bookworm)</a> and <a href="https://releases.ubuntu.com/mantic/">Ubuntu 23.10 (Mantic Minotaur)</a> to <a href="https://www.fmigo.net/">FmiGo</a>.
A bug that caused one test to hang put me off doing this for a while.
After a bunch of <code>printf()</code> debugging the bug turned out to be some kind of race condition in <a href="https://www.mpich.org/">mpich</a> when calling <code>MPI_Finalize()</code>.
I couldn't figure out how to fix the issue, despite following the documentation's recommendation to make the call the last thing the program does.
Therefore I switched the Dockerfile for <code>bookworm</code> to use <a href="https://www.open-mpi.org/">OpenMPI</a> instead.
Fortunately FmiGo is already engineered to make such a switch easy.</p>
<p>It has also occurred to me that the SPOOK solver used in FmiGo is a form of <a href="https://en.wikipedia.org/wiki/Feed_forward_(control)">feedforward control</a>.
This contrasts with <a href="https://en.wikipedia.org/wiki/Feedback">feedback control</a> in that feedforward controllers must model the system under regulation whereas feedback controllers do not.
This also means feedforward is <em>ex-ante</em> whereas feedback is <em>ex-post</em>.
Some readers may already suspect where I'm going with this: planning.
However that is the topic of a future post I am working on, and I intend to keep this post short.
Stay tuned!</p>Informatik 2023 talk2023-10-02T10:39:52+02:002023-10-02T10:39:52+02:00tomastag:www.härdin.se,2023-10-02:/blog/2023/10/02/informatik-2023-talk/<video width="1280" height="720" poster="http://www.härdin.se/files/videos/informatik2023.jpg" controls style="max-width:100%;height:auto">
<source src="http://www.härdin.se/files/videos/informatik2023_720p.mp4" type="video/mp4"/>
<source src="http://www.härdin.se/files/videos/informatik2023_720p.webm" type="video/webm"/>
Your browser does not support the video tag :(
</video>
<p>This is a recording of a talk I held remotely at the <a href="https://informatik2023.gi.de/">Gesellschaft für Informatik conference</a> in Berlin on September 29th 2023.</p>
<p><a href="http://www.härdin.se/files/videos/informatik2023.pdf">Click here to download the slides</a>.</p>
<p>The video is also <a href="https://www.youtube.com/watch?v=abFaLqOE4cg">mirrored on my YouTube channel</a>.</p>
<h2>Video download links</h2>
<p>Because HTML5 …</p><video width="1280" height="720" poster="http://www.härdin.se/files/videos/informatik2023.jpg" controls style="max-width:100%;height:auto">
<source src="http://www.härdin.se/files/videos/informatik2023_720p.mp4" type="video/mp4"/>
<source src="http://www.härdin.se/files/videos/informatik2023_720p.webm" type="video/webm"/>
Your browser does not support the video tag :(
</video>
<p>This is a recording of a talk I held remotely at the <a href="https://informatik2023.gi.de/">Gesellschaft für Informatik conference</a> in Berlin on September 29th 2023.</p>
<p><a href="http://www.härdin.se/files/videos/informatik2023.pdf">Click here to download the slides</a>.</p>
<p>The video is also <a href="https://www.youtube.com/watch?v=abFaLqOE4cg">mirrored on my YouTube channel</a>.</p>
<h2>Video download links</h2>
<p>Because HTML5 doesn't support specifying multiple resolutions in the <video> tag (only <picture> allows that) I have provided download links to alternative encodes below:</p>
<p>MP4: <a href="http://www.härdin.se/files/videos/informatik2023_1152p.mp4">1152p</a> (26M), <a href="http://www.härdin.se/files/videos/informatik2023_720p.mp4">720p</a> (22M), <a href="http://www.härdin.se/files/videos/informatik2023_540p.mp4">540p</a> (21M), <a href="http://www.härdin.se/files/videos/informatik2023_360p.mp4">360p</a> (20M)<br/>
WebM: <a href="http://www.härdin.se/files/videos/informatik2023_1152p.webm">1152p</a> (43M), <a href="http://www.härdin.se/files/videos/informatik2023_720p.webm">720p</a> (27M), <a href="http://www.härdin.se/files/videos/informatik2023_540p.webm">540p</a> (22M), <a href="http://www.härdin.se/files/videos/informatik2023_360p.webm">360p</a> (19M)</p>Workers and Resources parser published2023-07-17T20:38:57+02:002023-07-17T20:38:57+02:00tomastag:www.härdin.se,2023-07-17:/blog/2023/07/17/workers-and-resources-parser-published/<p>Leone recently asked me about the parser for the game <a href="https://www.sovietrepublic.net/">Workers & Resources: Soviet Republic</a> that I wrote about in the post <a href="http://www.härdin.se/blog/2021/12/08/mixed-integer-planning/">Mixed integer planning</a>.
It is licensed under the AGPL and available here: <a href="https://github.com/Tjoppen/workers_and_resources">workers_and_resources on GitHub</a>.</p>
<h2>Overview</h2>
<p>What the program does is parse the building definition files for all the …</p><p>Leone recently asked me about the parser for the game <a href="https://www.sovietrepublic.net/">Workers & Resources: Soviet Republic</a> that I wrote about in the post <a href="http://www.härdin.se/blog/2021/12/08/mixed-integer-planning/">Mixed integer planning</a>.
It is licensed under the AGPL and available here: <a href="https://github.com/Tjoppen/workers_and_resources">workers_and_resources on GitHub</a>.</p>
<h2>Overview</h2>
<p>What the program does is parse the building definition files for all the buildings in the game to figure out two things:</p>
<ul>
<li>how much resources and labour it takes to build them</li>
<li>what the buildings consume and produce, also known as their technical coefficients</li>
</ul>
<p>I haven't updated the code since 2021, but since the game is nearing its official release perhaps I will take another look at it.</p>
<h2>Data formats</h2>
<p>Let's take a closer look at the data files related to buildings, which are located in <code>media_soviet/buildings_types</code>.
Let's look at the gravel processing plant, which consists of three files:</p>
<ul>
<li><code>gravel_processing.ini</code></li>
<li><code>gravel_processing.bbox</code></li>
<li><code>gravel_processing.fire</code></li>
</ul>
<p>Let's ignore <code>gravel_processing.fire</code> because my code doesn't use it.</p>
<h3>.bbox files</h3>
<p><code>gravel_processing.bbox</code> defines multiple bounding boxes which have names like <code>techShape5</code> and <code>concreteShape1</code>.
The files are little-endian and the first four bytes are a 32-bit integer specifying the number of bounding boxes in the file.
Each bounding box is exactly 540 bytes and consists of the following:</p>
<ul>
<li>name (512 bytes, string)</li>
<li>index (4 bytes, uint32, counts up from zero)</li>
<li>xmin, ymin, zmin, xmax, ymax, zmax (4*6 = 24 bytes, float32)</li>
</ul>
<p>The names are NUL terminated but often not NUL filled, so there may be interesting strings in them.
The index doesn't appear to be useful.
The six floating point values define the bounding box; minimum and maximum in all three cardinal directions.</p>
<h3>.ini files</h3>
<p>The .ini files are text and look like this:</p>
<div class="highlight"><pre><span></span><code><span class="err">$</span><span class="n">NAME</span><span class="w"> </span><span class="mi">6158</span>
<span class="err">$</span><span class="n">VEHICLE_STATION</span><span class="w"> </span><span class="mf">65.4619</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="o">-</span><span class="mf">15.1333</span><span class="w"> </span><span class="mf">65.4619</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="mf">3.5876</span>
<span class="err">$</span><span class="n">VEHICLE_STATION</span><span class="w"> </span><span class="mf">68.4619</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="o">-</span><span class="mf">15.1333</span><span class="w"> </span><span class="mf">68.4619</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="mf">3.5876</span>
<span class="err">$</span><span class="n">TYPE_FACTORY</span>
<span class="err">$</span><span class="n">WORKERS_NEEDED</span><span class="w"> </span><span class="mi">15</span>
<span class="err">$</span><span class="n">PRODUCTION</span><span class="w"> </span><span class="n">gravel</span><span class="w"> </span><span class="mf">5.5</span>
<span class="err">$</span><span class="n">CONSUMPTION</span><span class="w"> </span><span class="n">rawgravel</span><span class="w"> </span><span class="mf">8.0</span>
<span class="err">$</span><span class="n">CONSUMPTION_PER_SECOND</span><span class="w"> </span><span class="n">eletric</span><span class="w"> </span><span class="mf">0.4</span>
<span class="o">[</span><span class="n">snip</span><span class="o">]</span>
</code></pre></div>
<p>Just from the strings we can get the gist of what the file is doing.
This file specifies a factory that consumes raw gravel and electricity and outputs gravel.
The rates of consumptions are also given, and are per worker multiplied by some factor to give a per second rate.
There is also a spelling error in "eletric" (should be "electric") which has thrown me off many times.</p>
<p>For most buildings the cost to build them aren't actually given explicitly.
Instead they are derived from the bounding boxes mentioned earlier.
For example the gravel processing plant has these lines (heavily abbreviated):</p>
<div class="highlight"><pre><span></span><code>$COST_WORK SOVIET_CONSTRUCTION_GROUNDWORKS 0.0
$COST_RESOURCE_AUTO ground_asphalt 1.0
$COST_WORK SOVIET_CONSTRUCTION_SKELETON_CASTING 1.0
$COST_RESOURCE_AUTO wall_concrete 0.8
$COST_WORK SOVIET_CONSTRUCTION_STEEL_LAYING 1.0
$COST_RESOURCE_AUTO wall_steel 0.35
</code></pre></div>
<p>What these do is tell the game to compute the resources required to build the plant from a bunch of formulas that operate on relevant bounding boxes.
I had initially intended to reverse engineer these formulas using least squares fitting, but I reached out to 3DIVISION first and got a reply from Peter Adamcik who gratiously provided me with a snippet of the actual C++ code that computes these automatic costs.
Thanks Peter!</p>
<p>The ground area, the wall area and the volume of each relevant bounding box are summed up into three separate variables that I have dubbed <math>
<mi>g</mi>
</math>, <math>
<mi>w</mi>
</math> and <math>
<mi>v</mi>
</math> respectively.
The first argument in <code>$COST_RESOURCE_AUTO</code> then says which formula to use.
For example <code>ground_asphalt</code>, which is the foundation of the plant, uses <math>
<mrow><mi>k</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mi>g</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>300</mn><mo lspace="0.222em" rspace="0.222em">+</mo><mn>0</mn><mo lspace="0" rspace="0">.</mo><mn>08</mn><mi>v</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>3000</mn></mrow>
</math> and <math>
<mrow><mn>150</mn><mi>k</mi></mrow>
</math> workdays, <math>
<mrow><mn>13</mn><mi>k</mi></mrow>
</math> tons of concrete, <math>
<mrow><mn>10</mn><mi>k</mi></mrow>
</math> tons of gravel and <math>
<mrow><mn>8</mn><mi>k</mi></mrow>
</math> tons of asphalt.
The second argument (1.0) is a further scaling factor.
This step (called <code>SOVIET_CONSTRUCTION_GROUNDWORKS</code>) has to be completed before the construction crew can start on the next phase of construction (<code>SOVIET_CONSTRUCTION_SKELETON_CASTING</code>).</p>
<p>Some buildings need extra resources that are given explicitly in the .ini file.</p>
<h2><code>lp_solve</code> generator</h2>
<p>Another part of the code (<code>generate_lp.py</code>) generates linear programs in <code>lp_solve</code> format.
These are fed into <code>lp_solve</code> and the resulting solution can then be further processed.
It is in the generator that the main experimentation happens.
One can set up scenarios like "maximize gravel production over 1 year" or "maximize dollar revenue from exports over 10 years".
Time is taken into account, as is the fact that one has to build a whole plant before it can be put to use.
The latter is an integer constraint and makes the programs mixed integer programs.</p>
<h2>Results parser and GNU Octave code generator</h2>
<p><code>parse_result.py</code> performs two tasks:
parsing the output of <code>lp_solve</code> and generating GNU Octave code to plot it.
Yes I like writing generators.</p>
<h2><code>run.sh</code></h2>
<p><code>run.sh</code> runs the whole shebang and outputs plots like this one:</p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/mixed_integer_planning/gravel.png" alt="GNU Octave plot"/></p>
<p>The goal in this case was to maximize gravel by the last time step.
Production of raw gravel is stopped at time step 14 so as to reassign workers to gravel processing.</p>Planning code published2023-06-13T13:23:44+02:002023-06-13T13:23:44+02:00tomastag:www.härdin.se,2023-06-13:/blog/2023/06/13/planning-code-published/<p>I recently got an email from Leone of the econophysics Discord <abbr title="I refuse to call them servers">channel</abbr> fame, asking for the code used in the post <a href="http://www.härdin.se/blog/2021/02/24/planning-complexity-for-model-economies/">Planning complexity for model economies</a>.
I've been meaning to publish it for quite a while, and this was as good an excuse as any to add license stuff and …</p><p>I recently got an email from Leone of the econophysics Discord <abbr title="I refuse to call them servers">channel</abbr> fame, asking for the code used in the post <a href="http://www.härdin.se/blog/2021/02/24/planning-complexity-for-model-economies/">Planning complexity for model economies</a>.
I've been meaning to publish it for quite a while, and this was as good an excuse as any to add license stuff and push it to a public repository: <a href="https://github.com/Tjoppen/power_law">power_law on GitHub</a>.
The code is licensed under the GNU Affero General Public License version 3 (AGPLv3).
I'm not a huge fan of GitHub but I also don't want to delay this release by hunting for a better host.</p>
<h2>Some words on licensing</h2>
<p>I've been advocating licensing as much code as possible under the terms of the AGPL.
The reason for this is because Facebook, Apple, Microsoft, Google etc. all hate it because it is an even bigger threat to their business models than the regular GNU General Public License (GPL) is.
I advocate for it rather than any of the "copyfarleft" licenses that have been popping up lately, for example the <a href="https://wiki.p2pfoundation.net/Peer_Production_License">Peer Production License</a>.
The reasons for this are the following:</p>
<ul>
<li>the GPL has been tested in court, and the AGPL is likely to also pass muster if it hasn't already</li>
<li>the AGPL is GPL compatible while many copyfarleft licenses are not</li>
<li>it works perfectly well in preventing Big Tech from using your code</li>
</ul>
<p>Regarding the PPL specifically, it can be circumvented by various means.
Standard retorts against market socialism apply.</p>
<p>I agree with what Luke Smith says about defanged licenses such as MIT and BSD, or as he calls them, <a href="https://lukesmith.xyz/articles/why-i-use-the-gpl-and-not-cuck-licenses/">cuck licenses</a>.
As Smith points out, these licenses do little more than provide free labour to the aforementioned companies.
Even worse, the permissive licensing of MINIX has directly helped Intel in its creation of the Management Engine backdoor in all modern Intel CPUs.
Smith is wrong about many things, but on this he is right.</p>
<p>I will add to what Smith is saying by saying that the GPL is not enough.
In the age of cloud (dis)services the GPL too lacks fangs.
Only the AGPL provides the necessary protection from companies hiding changes to your GPL work behind a SaaS cloud, thereby <em>extracting rent from your labour</em>.
Rent that you have allowed them to extract, because you refused to protect your code from it.</p>
<p>This said, standard caveats about strategic use of more permissive licenses (GPL, LGPL, even BSD/MIT) apply.
Programmers need to eat.</p>
<h2>A few words on language</h2>
<p>I dislike the use of the term "cuck" in political contexts, partly for its needlessly sexually charged character (much like <a href="https://en.wikipedia.org/wiki/GIMP">GIMP</a>), but also because it is inaccurate.
What we are talking about is not someone unwittingly raising someone else's offspring but something completely different.
The work has already been done, unlike brood parasitism where the work is to be done in the future.</p>
<p>What we have are people who unwittingly play for the opposing team, who act against the interests of their class.
They must be aware that companies may enclose their code, thereby removing it from the commons.
This happens because licenses like MIT and BSD lack the ability to defend themselves,
like an animal that has been declawed, dehorned or defanged, or which did not have claws, horns or fangs to begin with.
Many animals can and do defend themselves despite lacking these weapons, for example a doe may defend her fawn if pressed, by kicking and biting.
Anyway, the term "defang" is already in colloquial use and fits well so I have decided to use it.
"Toothless" could also work.</p>Quantifying autonomy in planning2023-05-21T19:59:46+02:002023-05-21T19:59:46+02:00tomastag:www.härdin.se,2023-05-21:/blog/2023/05/21/quantifying-autonomy-in-planning/<p>In the previous posts <a href="http://www.härdin.se/blog/2023/02/26/feasibility-is-optimal/">Feasibility is optimal</a> and <a href="http://www.härdin.se/blog/2023/04/23/on-self-concordant-convergence/">On self-concordant convergence</a> I have made the case that seeking centrality may be better than trying to optimize on some objective function.
The reason for this is two-fold:</p>
<ul>
<li>there is uncertainty in the data that make up the constraints</li>
<li>seeking centrality gives …</li></ul><p>In the previous posts <a href="http://www.härdin.se/blog/2023/02/26/feasibility-is-optimal/">Feasibility is optimal</a> and <a href="http://www.härdin.se/blog/2023/04/23/on-self-concordant-convergence/">On self-concordant convergence</a> I have made the case that seeking centrality may be better than trying to optimize on some objective function.
The reason for this is two-fold:</p>
<ul>
<li>there is uncertainty in the data that make up the constraints</li>
<li>seeking centrality gives each workplace more leeway</li>
</ul>
<p>In this post I will go into the second point, describing how we might quantify the amount of leeway/autonomy that can be provided to each workplace "no questions asked" by the system as a whole.</p>
<h2>Defining workplace autonomy</h2>
<p>What I mean by autonomy in this post is the extent to which each workplace can govern itself without threatening the feasibility of the system as a whole.
The less constrained each workplace is the more "free" the workers in that workplace are likely to be.
The more orthogonal its actions can be to the rest of the economy, the freeër it is.
But at the same time, no workplace is an island.</p>
<p>Excessive production of some products may induce demand or side-effects in other parts in the system that exceed the system's capabilities, thus violating feasibility.
Greenhouse gas emissions are the obvious example, but other issues like eutrophication are also a concern, as happens currently with the southern parts of the Baltic sea (<a href="https://jordbruksverket.se/jordbruket-miljon-och-klimatet/overgodning-och-lackage-av-vaxtnaring">Övergödning och läckage av växtnäring, <em>Eutrophication and leakage of plant fertilizer</em></a>, Jordbruksverket, fetched 2023-05-15).
Likewise insufficient production will cause shortages in downstream workplaces, also violating feasibility.</p>
<p>A maker of electric motors may speculatively try to make products in excess of the supply of rare-earth elements for magnets, which obviously will cause shortages in other parts of the economy, and thus such production should be discouraged.
But if they don't exceed said supply, then it may be worthwhile to produce more than is currently demanded because tooling costs amortize.
This would lower the cost of the products overall, and allow the workers there to take time off.
Therefore for work scheduling purposes it would be useful to know within what bounds production can be guaranteed to proceed smoothly, assuming sufficiently accurate data in the relevant parts of the system.
The more orthogonal a workplace is to the rest of the economy, the easier the scheduling of its work becomes.</p>
<p>Being able to answer these questions by machine quickly means less bureaucracy, also an obvious boon to workplace autonomy.</p>
<p>Finally, when workers in a workplace know that they can reduce production by a certain amount for a certain length of time, this allows exploring other production methods.
For example another type of plant can be planted or another gizmo invented using the resources so freed up.
We can imagine many remuneration schemes encouraging such exploration.
There is always a tradeoff between exploration and exploitation, a problem known as the <a href="https://en.wikipedia.org/wiki/Multi-armed_bandit">multi-armed bandit</a>.</p>
<h2>The geometry of workplace autonomy</h2>
<p>I have mentioned orthogonality above.
In this section I will show what this means.</p>
<p>Let us for simplicity in visualization imagine two workplaces, A and B.
A makes product a and B makes product b.
It is estimated by both workplaces independently that for some time period A can produce between 0-100 units of a and B can produce 0-50 units of b.
Each unit of a and b produces one unit of emissions, and the total amount of emissions are to be kept below 110.
The estimated demand for a is 40 and the estimated demand for b is 10.
Let us assume that the center of the system is at <math>
<mrow><mi>a</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>60</mn></mrow>
</math>, <math>
<mrow><mi>b</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>20</mn></mrow>
</math>.
The situation looks like the following figure:</p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/autonomy/system.svg" alt="The system in question. A rectangle with one corner lopped off."/></p>
<p>The diagonal line corresponds to the emissions constraint.
It may be tempting for each workplace to look at this and derive updated bounds on their own production without taking the other into consideration,
namely <math>
<mrow><mn>40</mn><mo lspace="0.278em" rspace="0.278em">≤</mo><mi>a</mi><mo lspace="0.278em" rspace="0.278em">≤</mo><mn>90</mn></mrow>
</math> and <math>
<mrow><mn>10</mn><mo lspace="0.278em" rspace="0.278em">≤</mo><mi>b</mi><mo lspace="0.278em" rspace="0.278em">≤</mo><mn>50</mn></mrow>
</math>:</p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/autonomy/system2.svg" alt="Lines drawn vertically and horizontally from the center of the system"/></p>
<p>However as sharp-eyed readers may realize, if both workplaces act entirely autonomously using only these bounds as reference then feasibility cannot be guaranteed.
The Cartesian product of the two bounds is a rectangle, part of which lies outside of the feasible region:</p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/autonomy/system3.svg" alt="A rectangle laid on top with the infeasible part of it colored red"/></p>
<p>The orthogonality I have mentioned is here apparent.
The rectangle's sides are orthogonal (at 90°) to one another.</p>
<p>There are many choices for feasible rectangles in this system, and the most straightforward one seems to be to scale the limits on both a and b down so that the upper-right corner of the rectangle lies on the emissions constraint, like so:</p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/autonomy/system4.svg" alt="A smaller rectangle that is entirely within the feasible region"/></p>
<p>The updated bounds are <math>
<mrow><mn>40</mn><mo lspace="0.278em" rspace="0.278em">≤</mo><mi>a</mi><mo lspace="0.278em" rspace="0.278em">≤</mo><mn>75</mn></mrow>
</math> and <math>
<mrow><mn>10</mn><mo lspace="0.278em" rspace="0.278em">≤</mo><mi>b</mi><mo lspace="0.278em" rspace="0.278em">≤</mo><mn>35</mn></mrow>
</math>.
Many other feasible bounds are possible.
This approach generalizes to any number of workplaces and production methods, meaning we can always fit some n-dimensional rectangle (<em>orthotope</em> or <em>box</em>) inside the system.
All that is necessary is that all corners of the box lie within the feasible region.</p>
<p>Other geometries are also possible.
Production within one workplace having two production methods available could be limited not just to a rectangle but any convex polygon, for example a hexagon.
The Cartesian product of such a polygon with another workplace having just one production method results in a <a href="https://en.wikipedia.org/wiki/Prism_(geometry)">prism</a>.</p>
<p><img style="display:block;width:33%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/autonomy/prism.svg" alt="A hexagonal prism"/></p>
<p>Note that the sides of the prism are orthogonal to its ends.
This orthogonality is again key to why autonomy can be guaranteed.
That the edges of the hexagons are not orthogonal to one another is here a strength, since this allows more autonomy <em>within</em> the associated workplace.
We can quantify the <em>degree</em> of autonomy by the area of the hexagon.
For the other workplace it is the length of the sides between the two hexagons.
For the system as a whole the <em>total</em> autonomy is the volume of the prism, which is just the product of the hexagon's area and the side length.</p>
<p>If the number of production methods <math>
<mi>n</mi>
</math> is larger than three then the result is a <a href="https://en.wikipedia.org/wiki/Prism_(geometry)#Prismatic_polytope">prismatic polytope</a>,
which are difficult to illustrate for obvious reasons.
Such polytopes have properties that make them easier to deal with computationally than polytopes in general.</p>
<p>Note that two or more workplaces coordinating their actions more tightly can get a combined larger volume to work within, at the cost of reduced autonomy and at the cost of more infernal meetings.
The figure below illustrates a situation where the heaxgonal workplace has more room to work within when the linear workplace is closer to the "lower" state.
The resulting shape is a frustrum.</p>
<p><img style="display:block;width:33%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/autonomy/frustrum.svg" alt="A hexagonal frustrum"/></p>
<p>It should hopefully be clear that the two workplaces are now dependent on more communication than before.
Note that the amount of necessary communication can be attenuated by an automatic plan solver.
But the roundtrip time inherent in that may be irritating to workplace coordination, for example when assigning shifts.
Hence a preference to autonomy.</p>
<h3>A small demo</h3>
<p>Apologies to those who are even more averse to JavaScript than I am, but I know of no way to do the following using just HTML+CSS.</p>
<p>The system below is the same as the one before.
Try dragging the slider and see what happens.
The dot doesn't move, sorry.
Patch welcome!</p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/autonomy/system4.svg" alt="A smaller rectangle that is entirely within the feasible region"/></p>
<script type="text/javascript">
function updateslider() {
var a = document.getElementById("a");
var b = document.getElementById("b");
var al = document.getElementById("al");
var bl = document.getElementById("bl");
var as = document.getElementById("as");
var bs = document.getElementById("bs");
var abs = document.getElementById("abs");
var ab = parseFloat(a.value) + parseFloat(b.value);
al.innerHTML = "a = " + a.value;
bl.innerHTML = "b = " + b.value;
abs.innerHTML = "a + b = " + ab;
if (ab > 110) {
as.style = bs.style = "background:red";
al.innerHTML += " BAD!";
bl.innerHTML += " BAD!";
abs.style = "font-weight:bold";
} else {
abs.style = "font-weight:none";
if (a.value > 75) {
as.style = "background:yellow";
al.innerHTML += " sus";
} else {
as.style = "background:green";
}
if (b.value > 35) {
bs.style = "background:yellow";
bl.innerHTML += " sus";
} else {
bs.style = "background:green";
}
}
}
window.onload = updateslider;
</script>
<div style="text-align: center">
40 <span id="as"><input type=range id=a min=40 max=100 value=60 onchange="updateslider()" oninput="updateslider()" list="markers" /></span> 100<br/>
<label for=a id=al></label>
</div>
<div style="text-align: center">
10 <span id="bs"><input type=range id=b min=10 max=50 value=20 onchange="updateslider()" oninput="updateslider()" list="markers" /></span> 50 <br/>
<label for=b id=bl></label><br/>
<span id=abs></span>
</div>
<p>A more complicated example would use multiple workplaces with multiple production methods and a simulated delay, showing how two or more workplaces stepping outside the box can result in infeasibility that isn't immediately visible.
Perhaps something for the future..</p>
<h2>A fast box fitting algorithm</h2>
<p>Consider the closed polytope <math>
<mrow><msup><mi>A</mi><mo lspace="0" rspace="0">′</mo></msup><mspace width="0"/><mi>x</mi><mo lspace="0.278em" rspace="0.278em">≥</mo><msup><mi>b</mi><mo lspace="0" rspace="0">′</mo></msup></mrow>
</math> with <math>
<mrow><msup><mi>A</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.278em" rspace="0.278em">∈</mo><msup><mi mathvariant="double-struck">R</mi><mrow><mi>m</mi><mo lspace="0" rspace="0">×</mo><mi>n</mi></mrow></msup></mrow>
</math> and a non-zero internal volume, and some internal point <math>
<mi>ξ</mi>
</math> around which we'd like to find a large n-dimensional box <math>
<mi>B</mi>
</math>.
Without loss of generality we can change the coordinate system to make the origin <math>
<mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>0</mn><mo lspace="0" rspace="0.167em">,</mo><mn>0</mn><mo lspace="0" rspace="0.167em">,</mo><mo lspace="0" rspace="0.167em">…</mo><mo lspace="0" rspace="0.167em">,</mo><mn>0</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> correspond to <math>
<mi>ξ</mi>
</math>.
The updated system is <math>
<mrow><mi>A</mi><mspace width="0"/><mi>x</mi><mo lspace="0.278em" rspace="0.278em">≥</mo><mi>b</mi></mrow>
</math> where all entries in <math>
<mi>b</mi>
</math> by necessity are negative.
If we want we can again without loss of generality scale each row in <math>
<mi>A</mi>
</math> so that all entries in <math>
<mi>b</mi>
</math> are -1.
The implementation does this, but for clarity the description does not.</p>
<p>Next introduce the positive vectors <math>
<mi>l</mi>
</math> and <math>
<mi>u</mi>
</math>, the lower and upper bounds that make up <math>
<mi>B</mi>
</math>, like so:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>B</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mo lspace="0" rspace="0" stretchy="false">{</mo><mi>x</mi><mtext> | </mtext><mo lspace="0" rspace="0">∀</mo><mi>i</mi><mo lspace="0.278em" rspace="0.278em">∈</mo><mo lspace="0" rspace="0" stretchy="false">[</mo><mn>1</mn><mo lspace="0" rspace="0.167em">,</mo><mi>n</mi><mo lspace="0" rspace="0.278em" stretchy="false">]</mo><mo lspace="0" rspace="0.278em">:</mo><mo lspace="0" rspace="0">-</mo><msub><mi>l</mi><mi>i</mi></msub><mo lspace="0.278em" rspace="0.278em">≤</mo><msub><mi>x</mi><mi>i</mi></msub><mo lspace="0.278em" rspace="0.278em">≤</mo><mo lspace="0" rspace="0">+</mo><msub><mi>u</mi><mi>i</mi></msub><mo lspace="0" rspace="0" stretchy="false">}</mo></mrow>
</math>
</span></p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/autonomy/lu.svg" alt="l and u in context"/></p>
<p>The <math>
<msup><mn>2</mn><mi>n</mi></msup>
</math> corners <math>
<mi>h</mi>
</math> of <math>
<mi>B</mi>
</math> have the coordinates <math>
<mrow><mi>h</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mo lspace="0" rspace="0">-</mo><msub><mi>l</mi><mn>1</mn></msub><mtext> or </mtext><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>u</mi><mn>1</mn></msub><mo lspace="0" rspace="0.167em">,</mo><mo lspace="0" rspace="0">-</mo><msub><mi>l</mi><mn>2</mn></msub><mtext> or </mtext><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>u</mi><mn>2</mn></msub><mo lspace="0" rspace="0.167em">,</mo><mo lspace="0" rspace="0.167em">…</mo><mo lspace="0" rspace="0.167em">,</mo><mo lspace="0" rspace="0">-</mo><msub><mi>l</mi><mi>n</mi></msub><mtext> or </mtext><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>u</mi><mi>n</mi></msub><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> and because <math>
<mrow><msub><mi>l</mi><mi>i</mi></msub><mo lspace="0.278em" rspace="0.278em">></mo><mn>0</mn></mrow>
</math> and <math>
<mrow><msub><mi>u</mi><mi>i</mi></msub><mo lspace="0.278em" rspace="0.278em">></mo><mn>0</mn></mrow>
</math> the origin is always contained in the box.
It is easy to see that the (hyper)volume of the box is</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>V</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mo lspace="0" rspace="0.167em" stretchy="false">∏</mo><msub><mi>l</mi><mi>i</mi></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>u</mi><mi>i</mi></msub></mrow>
</math>
</span></p>
<p>We would ideally like to compute the largest feasible box that contains the origin, or if we can't guarantee optimality then we at least want a box that is not unreasonably small.
The algorithm proposed here is one that produces a reasonable, but not necessarily optimal, <math>
<mi>B</mi>
</math>.</p>
<p>We start by observing that for all rows <math>
<msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup>
</math> there is a set of corners that minimize the scalar product with <math>
<msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup>
</math>.
In other words the corners that violates the constraint <math>
<mrow><msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup><mspace width="0"/><mi>h</mi><mo lspace="0.278em" rspace="0.278em">≥</mo><mi>b</mi></mrow>
</math> the most, or if they don't violate it then they are the least slack.
These corners have signs opposite of <math>
<msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup>
</math>.
Dimensions corresponding to zeros in <math>
<msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup>
</math> are irrelevant.
We can therefore describe the entire set of corners by <math>
<msup><mi>h</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup>
</math> with signs opposite of <math>
<msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup>
</math>, including zeros (which are set to zero in <math>
<msup><mi>h</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup>
</math>), like so:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msubsup><mi>h</mi><mi>j</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msubsup><mo lspace="0.278em" rspace="0.278em">=</mo><mrow><mo stretchy="true">{</mo><mrow><mstyle scriptlevel="0"><mtable columnalign="left"><mtr><mtd><mo lspace="0" rspace="0">-</mo><msub><mi>l</mi><mi>j</mi></msub></mtd><mtd><mtext>if </mtext><msub><mi>a</mi><mrow><mi>i</mi><mo lspace="0" rspace="0">,</mo><mi>j</mi></mrow></msub><mo lspace="0.278em" rspace="0.278em">></mo><mn>0</mn></mtd></mtr><mtr><mtd><mo lspace="0" rspace="0">+</mo><msub><mi>u</mi><mi>j</mi></msub></mtd><mtd><mtext>if </mtext><msub><mi>a</mi><mrow><mi>i</mi><mo lspace="0" rspace="0">,</mo><mi>j</mi></mrow></msub><mo lspace="0.278em" rspace="0.278em"><</mo><mn>0</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd><mtd><mtext>if </mtext><msub><mi>a</mi><mrow><mi>i</mi><mo lspace="0" rspace="0">,</mo><mi>j</mi></mrow></msub><mo lspace="0.278em" rspace="0.278em">=</mo><mn>0</mn></mtd></mtr></mtable></mstyle></mrow></mrow></mrow>
</math>
</span></p>
<p>If <math>
<msup><mi>h</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup>
</math> violates the constraint then we have</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup><mspace width="0"/><msup><mi>h</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0.278em" rspace="0.278em"><</mo><msub><mi>b</mi><mi>i</mi></msub></mrow>
</math>
</span></p>
<p>with both sides of the inequality negative.
We can easily compute a <math>
<msup><mi>k</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup>
</math> that turns this violated inequality into an equality:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msup><mi>k</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0.278em" rspace="0.278em">=</mo><mfrac><msub><mi>b</mi><mi>i</mi></msub><mrow><msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup><mspace width="0"/><msup><mi>h</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup></mrow></mfrac><mo lspace="0.278em" rspace="0.278em">⇒</mo><msup><mi>k</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mspace width="0"/><msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup><mspace width="0"/><msup><mi>h</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0.278em" rspace="0.278em">=</mo><msub><mi>b</mi><mi>i</mi></msub></mrow>
</math>
</span></p>
<p>Therefore diminishing the elements in <math>
<mi>l</mi>
</math> and <math>
<mi>u</mi>
</math> corresponding to the positive and negative elements in <math>
<msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup>
</math> respectively, by multiplying them by <math>
<msup><mi>k</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup>
</math>, results in a new <math>
<msup><mi>h</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup>
</math> that is feasible and as a result all other corners in <math>
<mi>B</mi>
</math> are also feasible with respect to <math>
<msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup>
</math>.
This because for entries corresponding to non-zeroes in <math>
<msup><mi>h</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup>
</math> flipping the sign always results in a scalar product that is greater than <math>
<mrow><msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup><mspace width="0"/><msup><mi>h</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup></mrow>
</math>, that is they are more slack.
Note that the diminishing of any entry in <math>
<mi>l</mi>
</math> or <math>
<mi>u</mi>
</math> moves entire sets of corners because <math>
<mi>B</mi>
</math> is parametrized in terms of these two vectors.
The corners move as a result of modifying the constraints that make up <math>
<mi>B</mi>
</math>.</p>
<p>The above implies that no feasible corner can ever be made infeasible by diminishing any of its corresponding elements in <math>
<mi>l</mi>
</math> and <math>
<mi>u</mi>
</math>.
The new box is always contained within the old box.
In the extreme we can diminish <math>
<mi>l</mi>
</math> and <math>
<mi>u</mi>
</math> so they are arbitrarily close to the origin, and we can always find some finite <math>
<mi>l</mi>
</math> and <math>
<mi>u</mi>
</math> that will fit the bill because the origin is strictly feasible by definition (<math>
<mrow><mi>A</mi><mn>0</mn><mo lspace="0.278em" rspace="0.278em">=</mo><mn>0</mn><mo lspace="0.278em" rspace="0.278em">></mo><mi>b</mi></mrow>
</math>) and so we can always squeeze <math>
<mi>l</mi>
</math> and <math>
<mi>u</mi>
</math> into the gap.
In fact this algorithm is motivated partly by improving the lower bound on the volume of <math>
<mi>B</mi>
</math>.
We can always compute a box that will fit by first fitting an <a href="https://en.wikipedia.org/wiki/Cross-polytope">orthoplex</a>, or more specifically a type of asymmetric <a href="https://en.wikipedia.org/wiki/Hyperrectangle#Dual_polytope">lozenge</a>, by tracing in the positive and negative cardinal directions, resulting in initial values for <math>
<mi>l</mi>
</math> and <math>
<mi>u</mi>
</math>.</p>
<p>To make the above less abstract let's look at some figures. Let's start with a polygon with the origin in its interior:</p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/autonomy/algo1.svg" alt="A convex polygon with the origin in its interior"/></p>
<p>By tracing in the cardinal directions we can fit a lozenge within it, which is guaranteed to always work because the polygon is convex:</p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/autonomy/algo2.svg" alt="Foo"/></p>
<p>Finding the rectangle that is the dual to this lozenge (blue) is easy, as is finding the rectangle to which the lozenge itself is the dual (red):</p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/autonomy/algo3.svg" alt="Foo"/></p>
<p>In general the lozenge has the following hypervolume:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msub><mi>V</mi><mi>lozenge</mi></msub><mo lspace="0.278em" rspace="0.278em">=</mo><mfrac><mn>1</mn><mrow><mi>n</mi><mo lspace="0" rspace="0">!</mo></mrow></mfrac><mo lspace="0.167em" rspace="0.167em" stretchy="false">∏</mo><msub><mi>l</mi><mi>i</mi></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>u</mi><mi>i</mi></msub></mrow>
</math>
</span></p>
<p>The smaller box provides a lower bound on the volume of the large box we seek:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msub><mi>V</mi><mi>lower</mi></msub><mo lspace="0.278em" rspace="0.278em">=</mo><mo lspace="0" rspace="0.167em" stretchy="false">∏</mo><mfrac><mrow><msub><mi>l</mi><mi>i</mi></msub><mo lspace="0" rspace="0">+</mo><msub><mi>u</mi><mi>i</mi></msub></mrow><mi>n</mi></mfrac><mo lspace="0.278em" rspace="0.278em">=</mo><mfrac><mn>1</mn><msup><mi>n</mi><mi>n</mi></msup></mfrac><mo lspace="0.167em" rspace="0.167em" stretchy="false">∏</mo><msub><mi>l</mi><mi>i</mi></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>u</mi><mi>i</mi></msub></mrow>
</math>
</span></p>
<p>The larger box naturally provides the upper bound:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msub><mi>V</mi><mi>upper</mi></msub><mo lspace="0.278em" rspace="0.278em">=</mo><mo lspace="0" rspace="0.167em" stretchy="false">∏</mo><msub><mi>l</mi><mi>i</mi></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>u</mi><mi>i</mi></msub></mrow>
</math>
</span></p>
<p>Obviously <math>
<mrow><msub><mi>V</mi><mi>upper</mi></msub><mo lspace="0" rspace="0" stretchy="false">/</mo><msub><mi>V</mi><mi>lower</mi></msub><mo lspace="0.278em" rspace="0.278em">=</mo><msup><mi>n</mi><mi>n</mi></msup></mrow>
</math> is a rather large range,
so the chances of us finding a box that is not so horrible are probably good.
Keeping in mind that <math>
<mrow><mi>n</mi><mo lspace="0.278em" rspace="0.278em">≈</mo><msup><mn>10</mn><mn>10</mn></msup></mrow>
</math>, the <math>
<msub><mi>V</mi><mi>lower</mi></msub>
</math> bound is equivalent to say a cobbler having leeway to make anywhere between 9.999999999 and 10.000000001 shoes in a given period.
Not hooray.
So the point is to widen these bounds to something more reasonable, perhaps 5 to 15 shoes.</p>
<p>We are now ready to list the algorithm:</p>
<ol>
<li>Compute initial <math>
<mi>l</mi>
</math> and <math>
<mi>u</mi>
</math> by tracing lines in the positive and negative cardinal directions from the origin, assigning each entry based on the closest constraint encountered</li>
<li>For <math>
<mrow><mi>i</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1</mn><mo lspace="0.167em" rspace="0.167em">…</mo><mi>m</mi></mrow>
</math>:<ol>
<li>For <math>
<mrow><mi>j</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1</mn><mo lspace="0.167em" rspace="0.167em">…</mo><mi>n</mi></mrow>
</math> let <math>
<mrow><msubsup><mi>h</mi><mi>j</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msubsup><mo lspace="0.278em" rspace="0.278em">=</mo><mrow><mo stretchy="true">{</mo><mrow><mstyle scriptlevel="0"><mtable columnalign="left"><mtr><mtd><mo lspace="0" rspace="0">-</mo><msub><mi>l</mi><mi>j</mi></msub></mtd><mtd><mtext>if </mtext><msub><mi>a</mi><mrow><mi>i</mi><mo lspace="0" rspace="0">,</mo><mi>j</mi></mrow></msub><mo lspace="0.278em" rspace="0.278em">></mo><mn>0</mn></mtd></mtr><mtr><mtd><mo lspace="0" rspace="0">+</mo><msub><mi>u</mi><mi>j</mi></msub></mtd><mtd><mtext>if </mtext><msub><mi>a</mi><mrow><mi>i</mi><mo lspace="0" rspace="0">,</mo><mi>j</mi></mrow></msub><mo lspace="0.278em" rspace="0.278em"><</mo><mn>0</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd><mtd><mtext>if </mtext><msub><mi>a</mi><mrow><mi>i</mi><mo lspace="0" rspace="0">,</mo><mi>j</mi></mrow></msub><mo lspace="0.278em" rspace="0.278em">=</mo><mn>0</mn></mtd></mtr></mtable></mstyle></mrow></mrow></mrow>
</math></li>
<li>If <math>
<mrow><msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup><mspace width="0"/><msup><mi>h</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0.278em" rspace="0.278em"><</mo><msub><mi>b</mi><mi>i</mi></msub></mrow>
</math><ol>
<li>Let <math>
<mrow><msup><mi>k</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0.278em" rspace="0.278em">=</mo><msub><mi>b</mi><mi>i</mi></msub><mo lspace="0" rspace="0" stretchy="false">/</mo><msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup><mspace width="0"/><msup><mi>h</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup></mrow>
</math></li>
<li>For <math>
<mrow><mi>j</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1</mn><mo lspace="0.167em" rspace="0.167em">…</mo><mi>n</mi></mrow>
</math> if <math>
<mrow><msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup><mo lspace="0.278em" rspace="0.278em">></mo><mn>0</mn></mrow>
</math> then update <math>
<mrow><msub><mi>l</mi><mi>j</mi></msub><mo lspace="0.278em" rspace="0">:</mo><mo lspace="0" rspace="0.278em">=</mo><msup><mi>k</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mspace width="0"/><msub><mi>l</mi><mi>j</mi></msub></mrow>
</math></li>
<li>For <math>
<mrow><mi>j</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1</mn><mo lspace="0.167em" rspace="0.167em">…</mo><mi>n</mi></mrow>
</math> if <math>
<mrow><msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup><mo lspace="0.278em" rspace="0.278em"><</mo><mn>0</mn></mrow>
</math> then update <math>
<mrow><msub><mi>u</mi><mi>j</mi></msub><mo lspace="0.278em" rspace="0">:</mo><mo lspace="0" rspace="0.278em">=</mo><msup><mi>k</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mspace width="0"/><msub><mi>u</mi><mi>j</mi></msub></mrow>
</math></li>
</ol>
</li>
</ol>
</li>
</ol>
<p>This results in something like the green rectangle in the figure below:</p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/autonomy/algo4.svg" alt="Foo"/></p>
<p>The complexity of a sparse implementation of the above algorithm is <math>
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>nnz</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>A</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math>.
The basic idea can be modified in various ways, for example permuting the rows in the system so that the algorithm processes them either in increasing or decreasing order of slackness.
Another possibility is making multiple passes, using smaller fractions of <math>
<msup><mi>k</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup>
</math> (say 10%), only using the full <math>
<msup><mi>k</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup>
</math> in the last pass.
Finally the elements in <math>
<mi>l</mi>
</math> and <math>
<mi>u</mi>
</math> need not be adjusted by the same <math>
<msup><mi>k</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup>
</math> but could use some other weighting as long as the result is that the corner is feasible.
Formulated as a diagonal matrix <math>
<msup><mi>K</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup>
</math>, we would then seek:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup><mspace width="0"/><msup><mi>K</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mspace width="0"/><msup><mi>h</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0.278em" rspace="0.278em">=</mo><msub><mi>b</mi><mi>i</mi></msub></mrow>
</math>
</span></p>
<p>Paralellizing the algorithm should also be possible, and should work well when there are few off-diagonal elements.
Such elements would need to be taken care of in a set of finishing passes.</p>
<p>Because <math>
<mi>l</mi>
</math> and <math>
<mi>u</mi>
</math> are very likely not equal, we can recenter the system by adding half their difference to <math>
<mi>ξ</mi>
</math>:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>ξ</mi><mo lspace="0.278em" rspace="0">:</mo><mo lspace="0" rspace="0.278em">=</mo><mi>ξ</mi><mo lspace="0.222em" rspace="0.222em">+</mo><mfrac><mrow><mi>u</mi><mo lspace="0" rspace="0">-</mo><mi>l</mi></mrow><mn>2</mn></mfrac></mrow>
</math>
</span></p>
<p>I am not sure what the convergence properties are of a method like this,
but one useful property is that no linear system solves are required.
That makes such a method similar to Katta Murty's most recent work.
In case it isn't obvious: after recentering, the above algorithm can be repeated and then the system recentered yet again etc.</p>
<p>A GNU Octave implementation is listed at the end of this post.</p>
<h2>Other shapes</h2>
<p>The algorithm above is limited to the box geometry and does not play well with for example sum constraints.
To make the problem more visible, let's take a farm as an example.</p>
<p>Let us presume that we can plant three types of crops in a region: potatoes, barley and wheat.
Because we have a fixed amount of land available, let's say 30 hectares, we might quantify this as:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mn>0</mn><mo lspace="0.278em" rspace="0.278em">≤</mo><mtext>potatoes</mtext></mrow>
</math>
</span></p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mn>0</mn><mo lspace="0.278em" rspace="0.278em">≤</mo><mtext>barley</mtext></mrow>
</math>
</span></p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mn>0</mn><mo lspace="0.278em" rspace="0.278em">≤</mo><mtext>wheat</mtext></mrow>
</math>
</span></p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mtext>potatoes</mtext><mo lspace="0.222em" rspace="0.222em">+</mo><mtext>barley</mtext><mo lspace="0.222em" rspace="0.222em">+</mo><mtext>wheat</mtext><mo lspace="0.278em" rspace="0.278em">≤</mo><mn>30</mn></mrow>
</math>
</span></p>
<p>The algorithm above may output that 5-10 hectares of each of the three crops can be planted without inconveniencing anyone else.
This doesn't sound so bad, until one considers what happens if instead 3000 different crops are made available to the solver.
After all, why should the choice of crops be limited to only three?
In this case the solver would have little choice but to spit out 3000 individual bounds, each one something like "plant 50-100 square <em>meters</em> of this crop". For 3000 crops.</p>
<p>A more reasonable parametrization might be one that outputs a total area to plant, and perhaps minimum amounts of certain crucial crops.
Something like "plant 15-30 hectares in total of which at least 5 hectares are potatoes".
Geometrically this corresponds to a <a href="https://en.wikipedia.org/wiki/Simplex">simplex</a> which has had a smaller simplex subtracted from it.
In two dimensions this is a triangle with a smaller triangle taken out:</p>
<p><img style="display:block;width:33%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/autonomy/simplices.svg" alt="One triangle with a smaller triangle removed"/></p>
<p>This shape has <math>
<mrow><mn>2</mn><mi>n</mi></mrow>
</math> corners.
It would be nice if we could also introduce maximum constraints, but the resulting shape (a truncated simplex) has more than <math>
<msup><mn>2</mn><mi>n</mi></msup>
</math> corners in some cases.
Compare for example the <a href="https://en.wikipedia.org/wiki/8-simplex">8-simplex</a> (9 corners) to the <a href="https://en.wikipedia.org/wiki/Truncated_8-simplexes#Quadritruncated_8-simplex">quadritruncated 8-simplex</a> (<math>
<mrow><mn>9</mn><mo lspace="0" rspace="0">!</mo><mo lspace="0" rspace="0" stretchy="false">/</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>4</mn><mo lspace="0" rspace="0">!</mo><msup><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mn>2</mn></msup><mo lspace="0" rspace="0.278em">=</mo><mn>630</mn><mo lspace="0.278em" rspace="0.278em">></mo><msup><mn>2</mn><mn>8</mn></msup></mrow>
</math> corners).
This may or may not be a problem, depending on whether the corners that minimize slackness with respect to a given constraint can be found quickly.
Perhaps a reader has a solution. If so, let me know!
For a box the problem is easy, as demonstrated by the algorithm earlier.
The figure below of a <a href="https://en.wikipedia.org/wiki/Truncated_tetrahedron">truncated tetrahedron</a> with 12 corners drawn using <a href="https://solvespace.com/index.pl">SolveSpace</a> hopefully illustrates the problem:</p>
<p><img style="display:block;width:25%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/autonomy/truncated.png" alt="A truncated tetrahedron"/></p>
<p>Moving on, it bears repeating that these shapes represent the bounds within which production can happen with minimal coordination.
The necessary inputs will always be provided if staying within it.
It might be possible to "color outside the lines", but doing so means a risk of having to go to anywhere between zero and 10,000 meetings.
The illustration below might represent a typical situation:</p>
<p><img style="display:block;width:33%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/autonomy/simplices2.svg" alt="Similar as above but with colors"/></p>
<p>The green area is the same "safe" area as before, but around it is an orange area that will at least require a roundtrip to the planning cloud which may either accept or reject the proposal.
It might also be necessary to go to meetings with workplaces both upstream and downstream.
Yes dear reader, I hate meetings.</p>
<h2>Appendix</h2>
<p>GNU Octave implementation of the algorithm.</p>
<div class="highlight"><pre><span></span><code><span class="n">n</span> <span class="p">=</span> <span class="mi">64</span><span class="p">;</span>
<span class="n">m</span> <span class="p">=</span> <span class="n">n</span><span class="o">*</span><span class="mi">100</span><span class="p">;</span> <span class="c">% the larger the ratio m:n the lower max_k becomes</span>
<span class="n">q</span> <span class="p">=</span> <span class="mi">160</span><span class="p">;</span>
<span class="c">% generate system</span>
<span class="k">function</span><span class="w"> </span>[A,b,x]<span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nf">generate</span><span class="p">(</span>m, n, q<span class="p">)</span>
<span class="w"> </span><span class="n">m</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">q</span>
<span class="n">A</span> <span class="p">=</span> <span class="nb">sprandn</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="nb">min</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="n">q</span><span class="o">/</span><span class="n">m</span><span class="p">));</span>
<span class="c">% without loss of generality we can let b be all -1's</span>
<span class="c">% this makes loz() a bit simpler</span>
<span class="n">b</span> <span class="p">=</span> <span class="o">-</span><span class="nb">ones</span><span class="p">(</span><span class="n">m</span><span class="p">,</span><span class="mi">1</span><span class="p">);</span>
<span class="n">x</span> <span class="p">=</span> <span class="nb">zeros</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="mi">1</span><span class="p">);</span>
<span class="k">endfunction</span>
<span class="c">% compute largest lozenge centered on x</span>
<span class="k">function</span><span class="w"> </span>[l,u]<span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nf">loz</span><span class="p">(</span>A, b, x<span class="p">)</span>
<span class="w"> </span><span class="n">n</span> <span class="p">=</span> <span class="nb">size</span><span class="p">(</span><span class="n">A</span><span class="p">,</span><span class="mi">2</span><span class="p">);</span>
<span class="n">l</span> <span class="p">=</span> <span class="nb">zeros</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="mi">1</span><span class="p">);</span> <span class="c">% minuses</span>
<span class="n">u</span> <span class="p">=</span> <span class="nb">zeros</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="mi">1</span><span class="p">);</span> <span class="c">% pluses</span>
<span class="k">for</span> <span class="n">i</span> <span class="p">=</span> <span class="mi">1</span><span class="p">:</span><span class="n">n</span>
<span class="c">% this can fail for very sparse A because sometimes there are no positives and/or negatives in a column</span>
<span class="c">% this only works when b is all -1's, I can't be bothered making it prettier because it's not necessary</span>
<span class="n">l</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="p">=</span> <span class="mf">1.</span><span class="o">/</span><span class="nb">full</span><span class="p">(</span><span class="nb">max</span><span class="p">(</span><span class="n">A</span><span class="p">(</span><span class="nb">find</span><span class="p">(</span><span class="n">A</span><span class="p">(:,</span><span class="n">i</span><span class="p">)</span><span class="o">></span><span class="mi">0</span><span class="p">),</span><span class="n">i</span><span class="p">)));</span>
<span class="n">u</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="p">=</span> <span class="o">-</span><span class="mf">1.</span><span class="o">/</span><span class="nb">full</span><span class="p">(</span><span class="nb">min</span><span class="p">(</span><span class="n">A</span><span class="p">(</span><span class="nb">find</span><span class="p">(</span><span class="n">A</span><span class="p">(:,</span><span class="n">i</span><span class="p">)</span><span class="o"><</span><span class="mi">0</span><span class="p">),</span><span class="n">i</span><span class="p">)));</span>
<span class="k">endfor</span>
<span class="k">endfunction</span>
<span class="k">function</span><span class="w"> </span>[L,U]<span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nf">loz2box</span><span class="p">(</span>A, b, x, l, u<span class="p">)</span>
<span class="w"> </span><span class="p">[</span><span class="n">m</span><span class="p">,</span> <span class="n">n</span><span class="p">]</span> <span class="p">=</span> <span class="nb">size</span><span class="p">(</span><span class="n">A</span><span class="p">);</span>
<span class="k">for</span> <span class="n">i</span> <span class="p">=</span> <span class="mi">1</span><span class="p">:</span><span class="n">m</span>
<span class="c">% compute several times, checking each pass after the first one</span>
<span class="k">for</span> <span class="n">p</span> <span class="p">=</span> <span class="mi">1</span><span class="p">:</span><span class="mi">10</span>
<span class="k">if</span> <span class="n">p</span> <span class="o"><</span><span class="p">=</span> <span class="mi">2</span>
<span class="c">% pick the corner that is most ornery the first two times</span>
<span class="n">s</span> <span class="p">=</span> <span class="nb">full</span><span class="p">(</span><span class="nb">sign</span><span class="p">(</span><span class="n">A</span><span class="p">(</span><span class="n">i</span><span class="p">,:)));</span>
<span class="k">else</span>
<span class="c">% pick a random corner in subsequent passes</span>
<span class="n">s</span> <span class="p">=</span> <span class="mi">2</span><span class="o">*</span><span class="nb">floor</span><span class="p">(</span><span class="nb">rand</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="n">n</span><span class="p">)</span><span class="o">*</span><span class="mi">2</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="c">% the following also picks points on edges, but they are never as nasty</span>
<span class="c">% s = floor(rand(1,n)*3)-1;</span>
<span class="k">endif</span>
<span class="n">l0u</span> <span class="p">=</span> <span class="p">[</span><span class="n">l</span><span class="p">,</span><span class="nb">zeros</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="mi">1</span><span class="p">),</span><span class="n">u</span><span class="p">];</span>
<span class="n">delta</span> <span class="p">=</span> <span class="o">-</span><span class="p">(</span><span class="n">l0u</span><span class="p">((</span><span class="mi">1</span><span class="p">:</span><span class="n">n</span><span class="p">)</span><span class="o">+</span><span class="p">(</span><span class="n">s</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="n">n</span><span class="p">)</span><span class="o">.*</span><span class="n">s</span><span class="p">)</span><span class="o">'</span><span class="p">;</span>
<span class="n">d</span> <span class="p">=</span> <span class="n">A</span><span class="p">(</span><span class="n">i</span><span class="p">,:)</span><span class="o">*</span><span class="p">(</span><span class="n">x</span><span class="o">+</span><span class="n">delta</span><span class="p">)</span> <span class="o">-</span> <span class="n">b</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>
<span class="k">if</span> <span class="n">d</span> <span class="o"><</span> <span class="o">-</span><span class="nb">eps</span><span class="o">*</span><span class="nb">sqrt</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="k">if</span> <span class="n">p</span> <span class="o">></span> <span class="mi">1</span>
<span class="c">% this should never happen if we got l and u right</span>
<span class="n">s</span><span class="p">,</span> <span class="n">d</span>
<span class="nb">error</span><span class="p">(</span><span class="s">"d < 0 with p == 2"</span><span class="p">);</span>
<span class="k">endif</span>
<span class="n">f</span> <span class="p">=</span> <span class="n">A</span><span class="p">(</span><span class="n">i</span><span class="p">,:)</span><span class="o">*</span><span class="n">x</span> <span class="o">-</span> <span class="n">b</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>
<span class="n">k</span> <span class="p">=</span> <span class="mi">1</span> <span class="o">+</span> <span class="n">d</span> <span class="o">/</span> <span class="p">(</span><span class="n">f</span> <span class="o">-</span> <span class="n">d</span><span class="p">);</span>
<span class="k">for</span> <span class="n">j</span> <span class="p">=</span> <span class="mi">1</span><span class="p">:</span><span class="n">n</span>
<span class="k">if</span> <span class="n">s</span><span class="p">(</span><span class="n">j</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span>
<span class="n">u</span><span class="p">(</span><span class="n">j</span><span class="p">)</span> <span class="o">*=</span> <span class="n">k</span><span class="p">;</span>
<span class="k">elseif</span> <span class="n">s</span><span class="p">(</span><span class="n">j</span><span class="p">)</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span>
<span class="n">l</span><span class="p">(</span><span class="n">j</span><span class="p">)</span> <span class="o">*=</span> <span class="n">k</span><span class="p">;</span>
<span class="k">endif</span>
<span class="k">endfor</span>
<span class="k">endif</span>
<span class="k">endfor</span>
<span class="k">endfor</span>
<span class="n">L</span> <span class="p">=</span> <span class="n">l</span><span class="p">;</span>
<span class="n">U</span> <span class="p">=</span> <span class="n">u</span><span class="p">;</span>
<span class="k">endfunction</span>
<span class="c">% generate system and compute largest inscribed lozenge at x</span>
<span class="p">[</span><span class="n">A</span><span class="p">,</span><span class="n">b</span><span class="p">,</span><span class="n">x</span><span class="p">]</span> <span class="p">=</span> <span class="n">generate</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">q</span><span class="p">);</span>
<span class="p">[</span><span class="n">l</span><span class="p">,</span><span class="n">u</span><span class="p">]</span> <span class="p">=</span> <span class="n">loz</span><span class="p">(</span><span class="n">A</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">x</span><span class="p">);</span>
<span class="c">% compute volume of enclosing (max) and enclosed (min) boxes</span>
<span class="n">Vmin</span> <span class="p">=</span> <span class="nb">sum</span><span class="p">(</span><span class="n">log10</span><span class="p">((</span><span class="n">l</span><span class="o">+</span><span class="n">u</span><span class="p">)</span><span class="o">/</span><span class="n">n</span><span class="p">))</span>
<span class="n">Vmax</span> <span class="p">=</span> <span class="nb">sum</span><span class="p">(</span><span class="n">log10</span><span class="p">(</span><span class="n">l</span><span class="o">+</span><span class="n">u</span><span class="p">))</span>
<span class="c">% the lozenge is certainly larger than Vmin but also much smaller than Vmax</span>
<span class="n">Vloz</span> <span class="p">=</span> <span class="n">Vmax</span> <span class="o">-</span> <span class="nb">sum</span><span class="p">(</span><span class="n">log10</span><span class="p">(</span><span class="mi">1</span><span class="p">:</span><span class="n">n</span><span class="p">))</span>
<span class="c">% find a large box that is enclosed by Ax >= b</span>
<span class="p">[</span><span class="n">L</span><span class="p">,</span><span class="n">U</span><span class="p">]</span> <span class="p">=</span> <span class="n">loz2box</span><span class="p">(</span><span class="n">A</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="n">l</span><span class="p">,</span> <span class="n">u</span><span class="p">);</span>
<span class="n">V</span> <span class="p">=</span> <span class="nb">sum</span><span class="p">(</span><span class="n">log10</span><span class="p">(</span><span class="n">L</span><span class="o">+</span><span class="n">U</span><span class="p">))</span>
<span class="k">if</span> <span class="n">V</span> <span class="o"><</span> <span class="n">Vmin</span> <span class="o">||</span> <span class="n">V</span> <span class="o">></span> <span class="n">Vmax</span>
<span class="nb">error</span><span class="p">(</span><span class="s">"bad V"</span><span class="p">);</span>
<span class="k">endif</span>
<span class="c">% compute the maximum and geometric mean k either element were adjusted by</span>
<span class="n">a</span> <span class="p">=</span> <span class="p">[</span><span class="n">l</span><span class="o">./</span><span class="n">L</span><span class="p">;</span><span class="n">u</span><span class="o">./</span><span class="n">U</span><span class="p">];</span>
<span class="n">min_k</span> <span class="p">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="n">geometric_k</span> <span class="p">=</span> <span class="nb">mean</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="s">"g"</span><span class="p">)</span>
<span class="n">max_k</span> <span class="p">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
</code></pre></div>
<p>Example output:</p>
<div class="highlight"><pre><span></span><code><span class="n">octave</span><span class="o">:</span><span class="mi">1</span><span class="o">></span><span class="w"> </span><span class="n">cube</span>
<span class="n">m</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">6400</span>
<span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">64</span>
<span class="n">q</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">160</span>
<span class="n">Vmin</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">-</span><span class="mf">123.27</span>
<span class="n">Vmax</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">-</span><span class="mf">7.6718</span>
<span class="n">Vloz</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">-</span><span class="mf">96.775</span>
<span class="n">V</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">-</span><span class="mf">34.632</span>
<span class="n">min_k</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">1.1804</span>
<span class="n">geometric_k</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">2.7335</span>
<span class="n">max_k</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">10.760</span>
</code></pre></div>
<p>What we see here is that the volume of the computed <math>
<mi>B</mi>
</math> is between Vmax and Vloz.
The <math>
<msup><mi>k</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup>
</math>'s encountered are between 1/1.1804 and 1/10.760 with the geometric mean being 1/2.7335.
So the amount of leeway per workplace in the model above is around one third of the naïve min/max bounds computed locally in the lozenge step.
What these values are for a real economy would require research.
And again, a different geometry that plays more nicely with sum constraints would be desirable.</p>On self-concordant convergence2023-04-23T20:23:39+01:002023-04-23T20:23:39+01:00tomastag:www.härdin.se,2023-04-23:/blog/2023/04/23/on-self-concordant-convergence/<p>In the post <a href="http://www.härdin.se/blog/2023/02/26/feasibility-is-optimal/">Feasibility is optimal</a> I suggested introducing a new barrier function to guarantee faster convergence towards the analytical center of a polytope.
This turns out to be unnecessary or even detrimental, and in this post I will get into why.
This post also presents a potentially new result …</p><p>In the post <a href="http://www.härdin.se/blog/2023/02/26/feasibility-is-optimal/">Feasibility is optimal</a> I suggested introducing a new barrier function to guarantee faster convergence towards the analytical center of a polytope.
This turns out to be unnecessary or even detrimental, and in this post I will get into why.
This post also presents a potentially new result relating to convergence for a class of central path methods for linear programming which I will call medium-step methods.</p>
<p>After digging around for literature on self-concordant functions I came across the book <a href="https://web.stanford.edu/~boyd/cvxbook/bv_cvxbook.pdf">Convex Programming</a> by Stephen Boyd and Lieven Vandenberghe.
Chapter 9 of the book deals precisely with the kind of problem I'm wanting to solve, especially section 9.6.</p>
<p>I will also use the paper <a href="doi:10.1007/BF01580724">A polynomial-time algorithm, based on Newton's method, for linear programming</a> by James Renegar.
Using the notation from Renegar, the iteration bound on page 505 in <em>Convex Programming</em>, using optimal line search and 64-bit floating point accuracy, becomes:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mfrac><mrow><mn>20</mn><mo lspace="0" rspace="0">-</mo><mn>2</mn></mrow><mrow><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>4</mn><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>2</mn><msup><mo lspace="0" rspace="0" stretchy="false">)</mo><mn>2</mn></msup></mrow></mfrac><mspace width="0.167em"/><mrow><mo stretchy="true">(</mo><mrow><mi>f</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>ξ</mi><mo lspace="0" rspace="0.222em" stretchy="false">)</mo><mo lspace="0" rspace="0.222em">-</mo><mi>f</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msub><mi>x</mi><mn>0</mn></msub><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow><mo stretchy="true">)</mo></mrow><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>log</mi><mn>2</mn></msub><mspace width="0.167em"/><msub><mi>log</mi><mn>2</mn></msub><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><msup><mn>2</mn><mrow><mo lspace="0" rspace="0">-</mo><mn>53</mn></mrow></msup><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">≤</mo><mn>288</mn><mspace width="0.167em"/><mrow><mo stretchy="true">(</mo><mrow><mi>f</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msub><mi>x</mi><mn>0</mn></msub><mo lspace="0" rspace="0.222em" stretchy="false">)</mo><mo lspace="0" rspace="0.222em">-</mo><mi>f</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>ξ</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow><mo stretchy="true">)</mo></mrow><mo lspace="0.222em" rspace="0.222em">+</mo><mn>6</mn></mrow>
</math>
</span></p>
<p>All that remains is to work out a bound for <math>
<mrow><mi mathvariant="normal">Δ</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mi>f</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msub><mi>x</mi><mn>0</mn></msub><mo lspace="0" rspace="0.222em" stretchy="false">)</mo><mo lspace="0" rspace="0.222em">-</mo><mi>f</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>ξ</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math>.
Remember that <math>
<mi>f</mi>
</math> here is the barrier function, which we are minimizing.
Large values of <math>
<mi mathvariant="normal">Δ</mi>
</math> means slow convergence.
In particular it is purely detrimental to add large quadratic terms as I suggested in the previous post.
It may also be tempting to scale the barrier function down by some constant <math>
<mrow><mi>r</mi><mo lspace="0.278em" rspace="0.278em"><</mo><mn>1</mn></mrow>
</math> so as to reduce <math>
<mi mathvariant="normal">Δ</mi>
</math> and thus the number of iterations, for example using <math>
<mrow><mi>f</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>x</mi><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">=</mo><mi>r</mi><mspace width="0.167em"/><mi>log</mi><mspace width="0.167em"/><mi>x</mi></mrow>
</math>.
But such scaling violates the self-concordance constraint that sits at the heart of the complexity analysis that Boyd and Vandenberghe (really Nesterov and Nemirovski) provides:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mo lspace="0" rspace="0" stretchy="false">|</mo><msup><mi>f</mi><mrow><mo lspace="0" rspace="0">′</mo><mo lspace="0" rspace="0">′</mo><mo lspace="0" rspace="0">′</mo></mrow></msup><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>x</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0.278em" stretchy="false">|</mo><mo lspace="0" rspace="0.278em">≤</mo><mn>2</mn><msup><mi>f</mi><mrow><mo lspace="0" rspace="0">′</mo><mo lspace="0" rspace="0">′</mo></mrow></msup><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>x</mi><msup><mo lspace="0" rspace="0" stretchy="false">)</mo><mrow><mn>3</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>2</mn></mrow></msup></mrow>
</math>
</span></p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mn>2</mn><msup><mi>f</mi><mrow><mo lspace="0" rspace="0">′</mo><mo lspace="0" rspace="0">′</mo></mrow></msup><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>x</mi><msup><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mrow><mn>3</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>2</mn></mrow></msup><mo lspace="0" rspace="0.278em">=</mo><mfrac><mrow><mn>2</mn><msup><mi>r</mi><mrow><mn>3</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>2</mn></mrow></msup></mrow><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><msup><mi>x</mi><mn>2</mn></msup><msup><mo lspace="0" rspace="0" stretchy="false">)</mo><mrow><mn>3</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>2</mn></mrow></msup></mrow></mfrac><mo lspace="0.278em" rspace="0.278em">=</mo><mfrac><mrow><mn>2</mn><msup><mi>r</mi><mrow><mn>3</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>2</mn></mrow></msup></mrow><msup><mi>x</mi><mn>3</mn></msup></mfrac></mrow>
</math>
</span></p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mo lspace="0" rspace="0" stretchy="false">|</mo><msup><mi>f</mi><mrow><mo lspace="0" rspace="0">′</mo><mo lspace="0" rspace="0">′</mo><mo lspace="0" rspace="0">′</mo></mrow></msup><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>x</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0.278em" stretchy="false">|</mo><mo lspace="0" rspace="0.278em">=</mo><mfrac><mrow><mn>2</mn><mi>r</mi></mrow><msup><mi>x</mi><mn>3</mn></msup></mfrac></mrow>
</math>
</span></p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mfrac><mrow><mn>2</mn><mi>r</mi></mrow><mrow><mi>r</mi><mspace width="0"/><msup><mi>x</mi><mn>3</mn></msup></mrow></mfrac><mo lspace="0.278em" rspace="0.278em">≤</mo><mfrac><mrow><mn>2</mn><msup><mi>r</mi><mrow><mn>3</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>2</mn></mrow></msup></mrow><msup><mi>x</mi><mn>3</mn></msup></mfrac><mo lspace="0.278em" rspace="0.278em">⇔</mo><mn>1</mn><mo lspace="0.278em" rspace="0.278em">≤</mo><msqrt><mi>r</mi></msqrt></mrow>
</math>
</span></p>
<p>which is violated for <math>
<mrow><mi>r</mi><mo lspace="0.278em" rspace="0.278em"><</mo><mn>1</mn></mrow>
</math>.
It also makes sense that this kind of scaling should provide no benefit due to the affine invariant nature of the Newton method.</p>
<p>Finally, Boyd and Vandenberghe claim that Nesterov and Nemirovski provide an even tighter bound on the number of iterations, but I do not have access to the relevant work.
The following PDF on Nemirovski's website may contain relevant information but I have not read it yet: <a href="https://www2.isye.gatech.edu/~nemirovs/Lect_IPM.pdf">Interior point polynomial time methods in convex programming</a></p>
<h2>A conservative bound on Δ</h2>
<p>To get started, let's borrow and adapt some of Renegar's notation.
Renegar has the original system <math>
<mrow><mi>A</mi><mspace width="0"/><mi>x</mi><mo lspace="0.278em" rspace="0.278em">≥</mo><mi>b</mi></mrow>
</math> with <math>
<mrow><mi>A</mi><mo lspace="0.278em" rspace="0.278em">∈</mo><msup><mi mathvariant="double-struck">R</mi><mrow><mi>m</mi><mo lspace="0" rspace="0">×</mo><mi>n</mi></mrow></msup></mrow>
</math>.
So <math>
<mi>x</mi>
</math> has <math>
<mi>n</mi>
</math> dimensions, and we have <math>
<mi>m</mi>
</math> inequalities.
Renegar also introduces <math>
<mi>l</mi>
</math> extra inequalities, each one a copy of <math>
<mrow><msup><mi>c</mi><mi>T</mi></msup><mspace width="0"/><mi>x</mi><mo lspace="0.278em" rspace="0.278em">≥</mo><msup><mi>k</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup></mrow>
</math>.
These extra inequalities are moved forward at each step in the algorithm until we get close enough to the optimal solution.
This is the "broom" I've written about earlier.
Renegar ultimately uses <math>
<mrow><mi>l</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mi>m</mi></mrow>
</math>, but provides convergence analysis for other values of <math>
<mi>l</mi>
</math> which shall become useful.</p>
<p>When modifying a constraint in a system let <math>
<mrow><msup><mi>m</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.278em" rspace="0.278em">=</mo><mi>m</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mn>1</mn></mrow>
</math> and <math>
<mrow><mi>l</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1</mn></mrow>
</math> where the latter corresponds to the constraint we are changing.
Using <math>
<mrow><mi>l</mi><mo lspace="0.278em" rspace="0.278em">></mo><mn>1</mn></mrow>
</math> would be useless in what follows,
but I will try to preserve the analysis for other values of <math>
<mi>l</mi>
</math> in case it is useful to someone.</p>
<p>Each step <math>
<mi>j</mi>
</math> in the algorithm has an associated centroid <math>
<msup><mi>ξ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup>
</math>.
Define the function <math>
<mrow><msup><mtext mathvariant="bold">X</mtext><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>x</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> as follows:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msubsup><mtext mathvariant="bold">X</mtext><mi>i</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msubsup><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>x</mi><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">=</mo><mfrac><mrow><msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup><mspace width="0"/><mi>x</mi><mo lspace="0" rspace="0">-</mo><msub><mi>b</mi><mi>i</mi></msub></mrow><mrow><msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup><mspace width="0"/><msup><mi>ξ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0" rspace="0">-</mo><msub><mi>b</mi><mi>i</mi></msub></mrow></mfrac></mrow>
</math>
</span></p>
<p>where <math>
<mrow><mn>1</mn><mo lspace="0.278em" rspace="0.278em">≤</mo><mi>i</mi><mo lspace="0.278em" rspace="0.278em">≤</mo><msup><mi>m</mi><mo lspace="0" rspace="0">′</mo></msup></mrow>
</math> correspond to the constraints that are not changing and <math>
<mrow><msup><mi>m</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.222em" rspace="0.222em">+</mo><mn>1</mn><mo lspace="0.278em" rspace="0.278em">≤</mo><mi>i</mi><mo lspace="0.278em" rspace="0.278em">≤</mo><msup><mi>m</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.222em" rspace="0.222em">+</mo><mi>l</mi></mrow>
</math> to the one that does change (and copies of it, if any).
In other words <math>
<mrow><mtext mathvariant="bold">X</mtext><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>x</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> normalizes the coordinates <math>
<mrow><mi>A</mi><mspace width="0"/><mi>x</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mi>b</mi><mo lspace="0.278em" rspace="0.278em">∈</mo><msup><mi mathvariant="double-struck">R</mi><mi>m</mi></msup></mrow>
</math> by dividing them elementwise by <math>
<mrow><mi>A</mi><mspace width="0"/><msup><mi>ξ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0.222em" rspace="0.222em">-</mo><mi>b</mi></mrow>
</math>.
This means that <math>
<mrow><msup><mtext mathvariant="bold">X</mtext><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0" rspace="0" stretchy="false">(</mo><msup><mi>ξ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">=</mo><mi>e</mi></mrow>
</math> where <math>
<mi>e</mi>
</math> is all ones.
Renegar also shows that <math>
<mrow><msup><mi>e</mi><mi>T</mi></msup><mtext mathvariant="bold">X</mtext><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>x</mi><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">=</mo><mi>m</mi><mo lspace="0.278em" rspace="0.278em">=</mo><msup><mi>m</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.222em" rspace="0.222em">+</mo><mi>l</mi></mrow>
</math> for all feasible <math>
<mi>x</mi>
</math>.</p>
<p>If we move the constraint some fraction <math>
<mrow><mi>δ</mi><mo lspace="0.278em" rspace="0.278em"><</mo><mn>1</mn></mrow>
</math> towards <math>
<msup><mi>ξ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup>
</math>,
and if we started with a perfectly centered system (<math>
<mrow><mi>α</mi><mo lspace="0.278em" rspace="0.278em">=</mo><msub><mrow><mo lspace="0" rspace="0">∥</mo><msup><mtext mathvariant="bold">X</mtext><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0" rspace="0" stretchy="false">(</mo><msup><mi>ξ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0" rspace="0.222em" stretchy="false">)</mo><mo lspace="0" rspace="0.222em">-</mo><mi>e</mi><mo lspace="0" rspace="0">∥</mo></mrow><mn>2</mn></msub><mo lspace="0.278em" rspace="0.278em">=</mo><mn>0</mn></mrow>
</math>) then Renegar shows that the distance from this point to the center of the new system (<math>
<mrow><mi>β</mi><mo lspace="0.278em" rspace="0.278em">=</mo><msub><mrow><mo lspace="0" rspace="0">∥</mo><msup><mtext mathvariant="bold">X</mtext><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0">+</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0" rspace="0" stretchy="false">(</mo><msup><mi>ξ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0" rspace="0.222em" stretchy="false">)</mo><mo lspace="0" rspace="0.222em">-</mo><mi>e</mi><mo lspace="0" rspace="0">∥</mo></mrow><mn>2</mn></msub></mrow>
</math>) is bounded by</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msup><mi>β</mi><mn>2</mn></msup><mo lspace="0.222em" rspace="0.222em">-</mo><mfrac><mrow><mi>l</mi><mspace width="0"/><msup><mi>δ</mi><mn>2</mn></msup></mrow><mrow><mn>1</mn><mo lspace="0" rspace="0">-</mo><mi>δ</mi></mrow></mfrac><mi>β</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mfrac><mrow><mi>l</mi><mspace width="0"/><msup><mi>δ</mi><mn>2</mn></msup></mrow><mrow><mn>1</mn><mo lspace="0" rspace="0">-</mo><mi>δ</mi></mrow></mfrac><mo lspace="0.278em" rspace="0.278em">≤</mo><mn>0</mn></mrow>
</math>
</span></p>
<p>For <math>
<mrow><mi>l</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1</mn></mrow>
</math> this inequality has the solution</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>β</mi><mo lspace="0.278em" rspace="0.278em">≤</mo><mfrac><mi>δ</mi><mrow><mn>1</mn><mo lspace="0" rspace="0">-</mo><mi>δ</mi></mrow></mfrac></mrow>
</math>
</span></p>
<p>And for <math>
<mrow><mi>l</mi><mo lspace="0.278em" rspace="0.278em">≫</mo><mn>1</mn></mrow>
</math> and <math>
<mi>δ</mi>
</math> not too small it is roughly</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>β</mi><mo lspace="0.278em" rspace="0.278em">≲</mo><mfrac><mrow><mi>l</mi><mspace width="0"/><msup><mi>δ</mi><mn>2</mn></msup></mrow><mrow><mn>1</mn><mo lspace="0" rspace="0">-</mo><mi>δ</mi></mrow></mfrac></mrow>
</math>
</span></p>
<p>If for example <math>
<mrow><mi>δ</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>3</mn></mrow>
</math> and <math>
<mrow><mi>l</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1</mn></mrow>
</math> then <math>
<mrow><mi>β</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>2</mn></mrow>
</math>.
Note that we can never perfectly center any system due to limited machine precision,
so in reality <math>
<mi>α</mi>
</math> is somewhere around <math>
<mrow><mi>ϵ</mi><msqrt><mi>m</mi></msqrt></mrow>
</math>.
This turns out to not matter in this case - this small extra contribution gets rounded off in the end.</p>
<p>The question now is how large can <math>
<mi mathvariant="normal">Δ</mi>
</math> actually be?
Let's first express it in terms of <math>
<mtext mathvariant="bold">X</mtext>
</math>:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi mathvariant="normal">Δ</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mrow><mo stretchy="true">[</mo><mrow><mo lspace="0" rspace="0.167em">-</mo><msub><mo lspace="0" rspace="0.167em" stretchy="false">∑</mo><mi>i</mi></msub><mi>log</mi><mspace width="0.167em"/><mrow><mo stretchy="true">(</mo><mrow><msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup><mspace width="0"/><msup><mi>ξ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0.222em" rspace="0.222em">-</mo><msub><mi>b</mi><mi>i</mi></msub></mrow><mo stretchy="true">)</mo></mrow></mrow><mo stretchy="true">]</mo></mrow><mo lspace="0.222em" rspace="0.222em">-</mo><mrow><mo stretchy="true">[</mo><mrow><mo lspace="0" rspace="0.167em">-</mo><msub><mo lspace="0" rspace="0.167em" stretchy="false">∑</mo><mi>i</mi></msub><mi>log</mi><mspace width="0.167em"/><mrow><mo stretchy="true">(</mo><mrow><msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup><mspace width="0"/><msup><mi>ξ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0">+</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0.222em" rspace="0.222em">-</mo><msub><mi>b</mi><mi>i</mi></msub></mrow><mo stretchy="true">)</mo></mrow></mrow><mo stretchy="true">]</mo></mrow></mrow>
</math>
</span></p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mo lspace="0" rspace="0.278em">=</mo><mo lspace="0" rspace="0.167em">-</mo><msub><mo lspace="0" rspace="0.167em" stretchy="false">∑</mo><mi>i</mi></msub><mi>log</mi><mspace width="0.167em"/><mrow><mo stretchy="true">(</mo><mrow><mfrac><mrow><msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup><mspace width="0"/><msup><mi>ξ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0" rspace="0">-</mo><msub><mi>b</mi><mi>i</mi></msub></mrow><mrow><msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup><mspace width="0"/><msup><mi>ξ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0">+</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0" rspace="0">-</mo><msub><mi>b</mi><mi>i</mi></msub></mrow></mfrac></mrow><mo stretchy="true">)</mo></mrow></mrow>
</math>
</span></p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mo lspace="0" rspace="0.278em">=</mo><mo lspace="0" rspace="0.167em">-</mo><msub><mo lspace="0" rspace="0.167em" stretchy="false">∑</mo><mi>i</mi></msub><mi>log</mi><mspace width="0.167em"/><mrow><mo stretchy="true">(</mo><mrow><msubsup><mtext mathvariant="bold">X</mtext><mi>i</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0">+</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msubsup><mo lspace="0" rspace="0" stretchy="false">(</mo><msup><mi>ξ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow><mo stretchy="true">)</mo></mrow></mrow>
</math>
</span></p>
<p>Let's further introduce <math>
<mrow><mi>V</mi><mo lspace="0.278em" rspace="0.278em">=</mo><msup><mtext mathvariant="bold">X</mtext><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0">+</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0" rspace="0" stretchy="false">(</mo><msup><mi>ξ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0" rspace="0.222em" stretchy="false">)</mo><mo lspace="0" rspace="0.222em">-</mo><mi>e</mi></mrow>
</math>, meaning we have:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi mathvariant="normal">Δ</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mo lspace="0" rspace="0.167em">-</mo><msub><mo lspace="0" rspace="0.167em" stretchy="false">∑</mo><mi>i</mi></msub><mi>log</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>V</mi><mi>i</mi></msub><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math>
</span></p>
<p>Note that the sum over all elements in <math>
<mi>V</mi>
</math> is zero (<math>
<mrow><msup><mi>e</mi><mi>T</mi></msup><mspace width="0"/><mi>V</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>0</mn></mrow>
</math>).
Negative elements in <math>
<mi>V</mi>
</math> contribute positively to <math>
<mi mathvariant="normal">Δ</mi>
</math> (meaning raising it, worsening the iteration bound) whereas positive elements contribute negatively (improving the iteration bound).</p>
<p>We may obtain a simple upper bound for <math>
<mi mathvariant="normal">Δ</mi>
</math> by first bounding <math>
<mrow><mi>δ</mi><mo lspace="0.278em" rspace="0.278em">≤</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>3</mn></mrow>
</math> and therefore <math>
<mrow><mi>β</mi><mo lspace="0.278em" rspace="0.278em">≤</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>2</mn></mrow>
</math>.
If we desire to move the constraint further than <math>
<mrow><mi>δ</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>3</mn></mrow>
</math> then we can do so in multiple steps.
Next let <math>
<mi>V</mi>
</math> have exactly one negative element, <math>
<mrow><mo lspace="0" rspace="0">-</mo><mi>β</mi></mrow>
</math>, and let's pretend that all other elements are zero.
This cannot actually happen due to the zero sum constraint, so this upper bound is very conservative.
We therefore have</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi mathvariant="normal">Δ</mi><mo lspace="0.278em" rspace="0.278em">≤</mo><mo lspace="0" rspace="0.167em">-</mo><mi>log</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0.222em" rspace="0.222em">-</mo><mi>β</mi><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">=</mo><mi>log</mi><mspace width="0.167em"/><mn>2</mn><mo lspace="0.278em" rspace="0.278em">≈</mo><mn>0</mn><mo lspace="0" rspace="0">.</mo><mn>6931</mn></mrow>
</math>
</span></p>
<p>Because of the convexity and strictly decreasing nature of <math>
<mrow><mo lspace="0" rspace="0.167em">-</mo><mi>log</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>V</mi><mi>i</mi></msub><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> there is no combination of two or more negative elements that will yield a higher upper bound on <math>
<mi mathvariant="normal">Δ</mi>
</math>. We therefore have</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mtext>#Iterations</mtext><mo lspace="0.278em" rspace="0.278em">≤</mo><mo lspace="0" rspace="0" stretchy="false">⌈</mo><mn>288</mn><mspace width="0.167em"/><mi>log</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>2</mn><mo lspace="0" rspace="0.222em" stretchy="false">)</mo><mo lspace="0" rspace="0.222em">+</mo><mn>6</mn><mo lspace="0" rspace="0.278em" stretchy="false">⌉</mo><mo lspace="0" rspace="0.278em">=</mo><mn>206</mn></mrow>
</math>
</span></p>
<p>This is already a useful result because it means we can move any constraint a substantial portion of the distance to the current center, and recenter the system in a reasonable amount of time.
In particular we do not have to perform <math>
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msqrt><mi>m</mi></msqrt><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> Newton steps as we would otherwise expect.
Note that this does not help solve LP faster in general, because setting <math>
<mrow><mi>l</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1</mn></mrow>
</math> means overall convergence with respect to some objective function is slow.
Using assumption (3.2) of Renegar with <math>
<mi>α</mi>
</math> explicit:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msup><mi>k</mi><mtext>opt</mtext></msup><mo lspace="0.222em" rspace="0.222em">-</mo><msup><mi>k</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0.278em" rspace="0.278em">≤</mo><msup><mrow><mo stretchy="true">(</mo><mrow><mn>1</mn><mo lspace="0.222em" rspace="0.222em">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0.222em" rspace="0.222em">-</mo><mi>α</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mfrac><mrow><mi>δ</mi><mspace width="0"/><mi>l</mi></mrow><mrow><msup><mi>m</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0" rspace="0">+</mo><mi>l</mi></mrow></mfrac></mrow><mo stretchy="true">)</mo></mrow><mi>j</mi></msup><mo lspace="0.167em" rspace="0" stretchy="false">(</mo><msup><mi>k</mi><mtext>opt</mtext></msup><mo lspace="0.222em" rspace="0.222em">-</mo><msup><mi>k</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>0</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math>
</span></p>
<p>With <math>
<mrow><mi>δ</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>3</mn></mrow>
</math>, <math>
<mrow><mi>l</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1</mn></mrow>
</math> and <math>
<mrow><mi>α</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>0</mn></mrow>
</math>:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msup><mi>k</mi><mtext>opt</mtext></msup><mo lspace="0.222em" rspace="0.222em">-</mo><msup><mi>k</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0.278em" rspace="0.278em">≤</mo><msup><mrow><mo stretchy="true">(</mo><mrow><mn>1</mn><mo lspace="0.222em" rspace="0.222em">-</mo><mfrac><mn>1</mn><mrow><mn>3</mn><msup><mi>m</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0" rspace="0">+</mo><mn>3</mn></mrow></mfrac></mrow><mo stretchy="true">)</mo></mrow><mi>j</mi></msup><mo lspace="0.167em" rspace="0" stretchy="false">(</mo><msup><mi>k</mi><mtext>opt</mtext></msup><mo lspace="0.222em" rspace="0.222em">-</mo><msup><mi>k</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>0</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math>
</span></p>
<p>Which means that for every bit of desired accuracy we need to perform</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>j</mi><mo lspace="0.278em" rspace="0.278em">≈</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>3</mn><msup><mi>m</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.222em" rspace="0.222em">+</mo><mn>3</mn><mo lspace="0" rspace="0.167em" stretchy="false">)</mo><mi>log</mi><mspace width="0.167em"/><mn>2</mn><mo lspace="0.278em" rspace="0.278em">≈</mo><mn>2</mn><mi>m</mi></mrow>
</math>
</span></p>
<p>iterations, each one consisting of up to 206 Newton steps. Letting <math>
<mrow><mi>l</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mi>m</mi></mrow>
</math> and <math>
<mrow><mi>δ</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>13</mn><msqrt><mi>m</mi></msqrt><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> on the other hand results in only</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>j</mi><mo lspace="0.278em" rspace="0.278em">≈</mo><mn>28</mn><msqrt><mi>m</mi></msqrt><mspace width="0.167em"/><mi>log</mi><mspace width="0.167em"/><mn>2</mn><mo lspace="0.278em" rspace="0.278em">≈</mo><mn>20</mn><msqrt><mi>m</mi></msqrt></mrow>
</math>
</span></p>
<p>iterations, each one only a single Newton step. We cannot use say <math>
<mrow><mi>δ</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>13</mn></mrow>
</math> with <math>
<mrow><mi>l</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mi>m</mi></mrow>
</math> because then <math>
<mrow><mi>β</mi><mo lspace="0.278em" rspace="0.278em">≈</mo><mi>m</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>156</mn></mrow>
</math> and <math>
<mi mathvariant="normal">Δ</mi>
</math> will become large.</p>
<h2>An even better bound on Δ</h2>
<p>By making use of the sum constraint we can improve the bound on Δ.</p>
<p>Let <math>
<mrow><mi>V</mi><mo lspace="0.278em" rspace="0.278em">∈</mo><msup><mi mathvariant="double-struck">R</mi><mi>m</mi></msup></mrow>
</math> be the vector with a single negative element, all other elements positive and equal and <math>
<mrow><msub><mrow><mo lspace="0" rspace="0">∥</mo><mi>V</mi><mo lspace="0" rspace="0">∥</mo></mrow><mn>2</mn></msub><mo lspace="0.278em" rspace="0.278em">=</mo><mi>β</mi></mrow>
</math>.
For convenience let</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>a</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mi>β</mi><mfrac><mn>1</mn><msqrt><mi>m</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></msqrt></mfrac></mrow>
</math>
</span></p>
<p>then</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>V</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mrow><mo stretchy="true">(</mo><mrow><mo lspace="0" rspace="0">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>a</mi><mo lspace="0" rspace="0.167em">,</mo><mi>a</mi><mo lspace="0" rspace="0.167em">,</mo><mo lspace="0" rspace="0.167em">…</mo><mo lspace="0" rspace="0.167em">,</mo><mi>a</mi></mrow><mo stretchy="true">)</mo></mrow></mrow>
</math>
</span></p>
<p>Clearly <math>
<mrow><msup><mi>e</mi><mi>T</mi></msup><mspace width="0"/><mi>V</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>0</mn></mrow>
</math>, and</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msubsup><mrow><mo lspace="0" rspace="0">∥</mo><mi>V</mi><mo lspace="0" rspace="0">∥</mo></mrow><mn>2</mn><mn>2</mn></msubsup><mo lspace="0.278em" rspace="0.278em">=</mo><msup><mi>β</mi><mn>2</mn></msup><mfrac><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn><msup><mo lspace="0" rspace="0" stretchy="false">)</mo><mn>2</mn></msup><mo lspace="0" rspace="0">+</mo><mi>m</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow><mrow><mi>m</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></mfrac><mo lspace="0.278em" rspace="0.278em">=</mo><msup><mi>β</mi><mn>2</mn></msup></mrow>
</math>
</span></p>
<p>To see whether <math>
<mi>V</mi>
</math> maximizes <math>
<mi mathvariant="normal">Δ</mi>
</math> let us evaluate the gradient of the barrier function at <math>
<mi>V</mi>
</math> projected onto the null space of <math>
<mi>e</mi>
</math>.
First the unprojected gradient:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>g</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mo lspace="0" rspace="0">∇</mo><mi>f</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>V</mi><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">=</mo><mrow><mo stretchy="true">(</mo><mrow><mfrac><mrow><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow><mrow><mn>1</mn><mo lspace="0" rspace="0">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>a</mi></mrow></mfrac><mo lspace="0" rspace="0.167em">,</mo><mfrac><mrow><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow><mrow><mn>1</mn><mo lspace="0" rspace="0">+</mo><mi>a</mi></mrow></mfrac><mo lspace="0" rspace="0.167em">,</mo><mo lspace="0" rspace="0.167em">…</mo><mo lspace="0" rspace="0.167em">,</mo><mfrac><mrow><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow><mrow><mn>1</mn><mo lspace="0" rspace="0">+</mo><mi>a</mi></mrow></mfrac></mrow><mo stretchy="true">)</mo></mrow></mrow>
</math>
</span></p>
<p>We can perform the above mentioned projection by subtracting the average of the entries in <math>
<mi>g</mi>
</math> from <math>
<mi>g</mi>
</math> itself:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mover><mi>g</mi><mo accent="true">̂</mo></mover><mo lspace="0.278em" rspace="0.278em">=</mo><mi>g</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mi>e</mi><mfrac><mn>1</mn><mi>m</mi></mfrac><mspace width="0.167em"/><mrow><mo stretchy="true">(</mo><mrow><mfrac><mrow><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow><mrow><mn>1</mn><mo lspace="0" rspace="0">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>a</mi></mrow></mfrac><mo lspace="0.222em" rspace="0.222em">+</mo><mfrac><mrow><mo lspace="0" rspace="0">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow><mrow><mn>1</mn><mo lspace="0" rspace="0">+</mo><mi>a</mi></mrow></mfrac></mrow><mo stretchy="true">)</mo></mrow></mrow>
</math>
</span></p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mo lspace="0" rspace="0.278em">=</mo><mi>g</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mi>e</mi><mfrac><mn>1</mn><mi>m</mi></mfrac><mspace width="0.167em"/><mrow><mo stretchy="true">(</mo><mrow><mfrac><mrow><mo lspace="0" rspace="0">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0" rspace="0">+</mo><mi>a</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0" rspace="0">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>a</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0" rspace="0">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>a</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0" rspace="0">+</mo><mi>a</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></mfrac></mrow><mo stretchy="true">)</mo></mrow></mrow>
</math>
</span></p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mo lspace="0" rspace="0.278em">=</mo><mi>g</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mi>e</mi><mfrac><mn>1</mn><mi>m</mi></mfrac><mspace width="0.167em"/><mrow><mo stretchy="true">(</mo><mrow><mfrac><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn><msup><mo lspace="0" rspace="0" stretchy="false">)</mo><mn>2</mn></msup><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>a</mi><mo lspace="0" rspace="0">-</mo><mi>m</mi></mrow><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0" rspace="0">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>a</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0" rspace="0">+</mo><mi>a</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></mfrac></mrow><mo stretchy="true">)</mo></mrow></mrow>
</math>
</span></p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mo lspace="0" rspace="0.278em">=</mo><mi>g</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mi>e</mi><mfrac><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0" rspace="0">-</mo><mn>2</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>a</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0" rspace="0">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>a</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0" rspace="0">+</mo><mi>a</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></mfrac></mrow>
</math>
</span></p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mo lspace="0" rspace="0.278em">=</mo><mrow><mo stretchy="true">(</mo><mrow><mfrac><mrow><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow><mrow><mn>1</mn><mo lspace="0" rspace="0">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>a</mi></mrow></mfrac><mo lspace="0.222em" rspace="0.222em">-</mo><mfrac><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0" rspace="0">-</mo><mn>2</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>a</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0" rspace="0">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>a</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0" rspace="0">+</mo><mi>a</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></mfrac><mo lspace="0" rspace="0.167em">,</mo><mfrac><mrow><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow><mrow><mn>1</mn><mo lspace="0" rspace="0">+</mo><mi>a</mi></mrow></mfrac><mo lspace="0.222em" rspace="0.222em">-</mo><mfrac><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0" rspace="0">-</mo><mn>2</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>a</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0" rspace="0">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>a</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0" rspace="0">+</mo><mi>a</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></mfrac><mo lspace="0" rspace="0.167em">,</mo><mo lspace="0" rspace="0">…</mo></mrow><mo stretchy="true">)</mo></mrow></mrow>
</math>
</span></p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mo lspace="0" rspace="0.278em">=</mo><mfrac><mn>1</mn><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0" rspace="0">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>a</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0" rspace="0">+</mo><mi>a</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></mfrac><mspace width="0.167em"/><mrow><mo stretchy="true">(</mo><mrow><mo lspace="0" rspace="0">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0.222em" rspace="0.222em">+</mo><mi>a</mi><mo lspace="0" rspace="0.222em" stretchy="false">)</mo><mo lspace="0" rspace="0.222em">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mn>2</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>a</mi><mo lspace="0.222em" rspace="0.222em">+</mo><mn>1</mn><mo lspace="0" rspace="0.167em">,</mo><mo lspace="0" rspace="0">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0.222em" rspace="0.222em">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>a</mi><mo lspace="0" rspace="0.222em" stretchy="false">)</mo><mo lspace="0" rspace="0.222em">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mn>2</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>a</mi><mo lspace="0.222em" rspace="0.222em">+</mo><mn>1</mn><mo lspace="0" rspace="0.167em">,</mo><mo lspace="0" rspace="0">…</mo></mrow><mo stretchy="true">)</mo></mrow></mrow>
</math>
</span></p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mo lspace="0" rspace="0.278em">=</mo><mfrac><mn>1</mn><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0" rspace="0">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>a</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0" rspace="0">+</mo><mi>a</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></mfrac><mspace width="0.167em"/><mrow><mo stretchy="true">(</mo><mrow><mo lspace="0" rspace="0">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>a</mi><mo lspace="0" rspace="0.167em">,</mo><mi>a</mi><mo lspace="0" rspace="0.167em">,</mo><mo lspace="0" rspace="0.167em">…</mo><mo lspace="0" rspace="0.167em">,</mo><mi>a</mi></mrow><mo stretchy="true">)</mo></mrow></mrow>
</math>
</span></p>
<p>In other words:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mover><mi>g</mi><mo accent="true">̂</mo></mover><mo lspace="0.278em" rspace="0.278em">=</mo><mfrac><mn>1</mn><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0" rspace="0">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>a</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0" rspace="0">+</mo><mi>a</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></mfrac><mi>V</mi></mrow>
</math>
</span></p>
<p>But because <math>
<mi>V</mi>
</math> butts up against and is perpendicular to the <math>
<mrow><msub><mrow><mo lspace="0" rspace="0">∥</mo><mi>V</mi><mo lspace="0" rspace="0">∥</mo></mrow><mn>2</mn></msub><mo lspace="0.278em" rspace="0.278em">=</mo><mi>β</mi></mrow>
</math> constraint, and <math>
<mover><mi>g</mi><mo accent="true">̂</mo></mover>
</math> points in the same direction as <math>
<mi>V</mi>
</math>, therefore <math>
<mi>V</mi>
</math> is locally optimal.
Whether it is globally optimal is something that I conjecture is true, but I cannot prove it at present. At least one other local optimum exist, <math>
<mrow><mi>a</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mo lspace="0" rspace="0">-</mo><mi>β</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><msqrt><mi>m</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></msqrt></mrow>
</math> (signs merely flipped), but it can be shown to be inferior to its negative, as we shall soon see.
Moving on, we have the following conjectural bound:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi mathvariant="normal">Δ</mi><mo lspace="0.278em" rspace="0.278em">≤</mo><mo lspace="0" rspace="0.167em">-</mo><mi>log</mi><mspace width="0.167em"/><mrow><mo stretchy="true">(</mo><mrow><mn>1</mn><mo lspace="0.222em" rspace="0.222em">-</mo><mi>β</mi><msqrt><mfrac><mrow><mi>m</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow><mi>m</mi></mfrac></msqrt></mrow><mo stretchy="true">)</mo></mrow><mo lspace="0.222em" rspace="0.222em">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mn>1</mn><mo lspace="0" rspace="0.167em" stretchy="false">)</mo><mi>log</mi><mspace width="0.167em"/><mrow><mo stretchy="true">(</mo><mrow><mn>1</mn><mo lspace="0.222em" rspace="0.222em">+</mo><mi>β</mi><msqrt><mfrac><mn>1</mn><mrow><mi>m</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></mfrac></msqrt></mrow><mo stretchy="true">)</mo></mrow></mrow>
</math>
</span></p>
<p>And in the limit:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msub><mo lspace="0" rspace="0.167em">lim</mo><mrow><mi>m</mi><mo lspace="0" rspace="0">→</mo><mi mathvariant="normal">∞</mi></mrow></msub><mi mathvariant="normal">Δ</mi><mo lspace="0.278em" rspace="0.278em">≤</mo><mo lspace="0" rspace="0.167em">-</mo><mi>log</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0.222em" rspace="0.222em">-</mo><mi>β</mi><mo lspace="0" rspace="0.222em" stretchy="false">)</mo><mo lspace="0" rspace="0.222em">-</mo><mi>β</mi></mrow>
</math>
</span></p>
<p>Because we have limited <math>
<mrow><mi>β</mi><mo lspace="0.278em" rspace="0.278em">≤</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>2</mn></mrow>
</math> we therefore have</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi mathvariant="normal">Δ</mi><mo lspace="0.278em" rspace="0.278em">≤</mo><mi>log</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>2</mn><mo lspace="0" rspace="0.222em" stretchy="false">)</mo><mo lspace="0" rspace="0.222em">-</mo><mfrac><mn>1</mn><mn>2</mn></mfrac><mo lspace="0.278em" rspace="0.278em">≈</mo><mn>0</mn><mo lspace="0" rspace="0">.</mo><mn>1931</mn></mrow>
</math>
</span></p>
<p>If we use <math>
<mi>a</mi>
</math> with signs flipped we instead get <math>
<mrow><mo lspace="0" rspace="0.167em">-</mo><mi>log</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0.222em" rspace="0.222em">+</mo><mi>β</mi><mo lspace="0" rspace="0.222em" stretchy="false">)</mo><mo lspace="0" rspace="0.222em">+</mo><mi>β</mi><mo lspace="0.278em" rspace="0.278em">≈</mo><mn>0</mn><mo lspace="0" rspace="0">.</mo><mn>094535</mn></mrow>
</math>, which is inferior as previously stated.
The iteration bound therefore, conjecturally, improves to:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mtext>#Iterations</mtext><mo lspace="0.278em" rspace="0.278em">≤</mo><mrow><mo stretchy="true">⌈</mo><mrow><mn>288</mn><mspace width="0.167em"/><mrow><mo stretchy="true">(</mo><mrow><mi>log</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>2</mn><mo lspace="0" rspace="0.222em" stretchy="false">)</mo><mo lspace="0" rspace="0.222em">-</mo><mfrac><mn>1</mn><mn>2</mn></mfrac></mrow><mo stretchy="true">)</mo></mrow><mo lspace="0.222em" rspace="0.222em">+</mo><mn>6</mn></mrow><mo stretchy="true">⌉</mo></mrow><mo lspace="0.278em" rspace="0.278em">=</mo><mn>62</mn></mrow>
</math>
</span></p>
<p>We can do even better by optimizing the choice of <math>
<mi>δ</mi>
</math>.
The following Octave code shows that <math>
<mrow><mi>δ</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>6</mn></mrow>
</math> is optimal:</p>
<div class="highlight"><pre><span></span><code><span class="n">octave</span><span class="p">:</span><span class="mi">58</span><span class="o">></span> <span class="n">d</span><span class="p">=</span><span class="mf">0.01</span><span class="p">:</span><span class="mf">0.001</span><span class="p">:</span><span class="mf">0.4</span><span class="p">;</span> <span class="n">b</span><span class="p">=</span><span class="n">d</span><span class="o">./</span><span class="p">(</span><span class="mi">1</span><span class="o">-</span><span class="n">d</span><span class="p">);</span> <span class="n">it</span><span class="p">=(</span><span class="nb">ceil</span><span class="p">(</span><span class="mi">288</span><span class="o">*</span><span class="p">(</span><span class="o">-</span><span class="nb">log</span><span class="p">(</span><span class="mi">1</span><span class="o">-</span><span class="n">b</span><span class="p">)</span><span class="o">-</span><span class="n">b</span><span class="p">))</span><span class="o">+</span><span class="mi">6</span><span class="p">)</span><span class="o">.*</span><span class="nb">ceil</span><span class="p">(</span><span class="mf">1.</span><span class="o">/</span><span class="n">d</span><span class="o">/</span><span class="mi">3</span><span class="p">);</span> <span class="nb">plot</span><span class="p">(</span><span class="n">d</span><span class="p">,</span><span class="n">it</span><span class="p">);</span> <span class="p">[</span><span class="n">i</span><span class="p">,</span><span class="n">j</span><span class="p">]</span> <span class="p">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">it</span><span class="p">);</span> <span class="n">it</span><span class="p">(</span><span class="n">j</span><span class="p">),</span> <span class="n">d</span><span class="p">(</span><span class="n">j</span><span class="p">)</span>
<span class="n">ans</span> <span class="p">=</span> <span class="mi">26</span>
<span class="n">ans</span> <span class="p">=</span> <span class="mf">0.1670</span>
</code></pre></div>
<p><img style="display:block;width:75%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/convergence/iterations.png" alt="Octave plot with minimum circled"/></p>
<p>So as few as <math>
<mrow><mn>2</mn><mo lspace="0.222em" rspace="0.222em">*</mo><mn>13</mn><mo lspace="0.278em" rspace="0.278em">=</mo><mn>26</mn></mrow>
</math> Newtons steps will perform the same job that would otherwise require 62 steps with <math>
<mrow><mi>δ</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>3</mn></mrow>
</math>.
So conjecturally we are nearly an order of magnitude faster than the 206 figure in the previous section.</p>
<h2>Medium-step</h2>
<p>The term <em>medium-step</em> comes about for two reasons:
the existence of the term <em>long-step</em> in the literature and the much shorter steps taken in Renegar's paper compared to what is done here.</p>
<p>Renegar uses <math>
<mrow><mi>δ</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>13</mn><msqrt><mi>m</mi></msqrt><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> whereas I use <math>
<mrow><mi>δ</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>6</mn></mrow>
</math> above.
We could therefore call Renegar's <math>
<mi>δ</mi>
</math> <em>short-step</em>.
It requires <math>
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>L</mi><msqrt><mi>m</mi></msqrt><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> iterations.
On the other extreme, the type of predictor-corrector methods often used in practice are known as <em>long-step</em> methods.
They use <math>
<mrow><mi>δ</mi><mo lspace="0.278em" rspace="0.278em">≫</mo><mn>1</mn></mrow>
</math>, sometimes stepping as far as 99.9% of the distance to the boundary of the system.
Todd and Ye demonstrate that these methods have worst-case performance of <math>
<mrow><mi mathvariant="normal">Ω</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>L</mi><mroot><mi>m</mi><mn>3</mn></mroot><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> and, if I understand correctly, they remain <math>
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>L</mi><msqrt><mi>m</mi></msqrt><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math>.</p>
<p>Because the <math>
<mi>δ</mi>
</math> chosen above is inbetween these two extremes I have chosen to call the method medium-step.
Note again that this result is only useful if we seek to remain in the center of a linear program.
It is not useful if one seeks to optimize some objective function <math>
<mrow><msup><mi>c</mi><mi>T</mi></msup><mspace width="0"/><mi>x</mi></mrow>
</math>.</p>
<h2>Future work</h2>
<p>Further theoretical improvements could be made by analyzing what I will call medium-step predictor-corrector methods.
By computing the tangent to the central path using a short step, a line search can be performed for finding a better initial guess in the system updated with <math>
<mrow><mi>δ</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>6</mn></mrow>
</math>.
This is likely to bring down the number of Newton steps.
By how much I am not sure.
Note that computing this tangent itself costs a small number of Newton steps.
On the other hand the system is likely to be better conditioned compared to just after a medium-step update, meaning these Newton steps are cheaper to compute.</p>
<h2>Closing remarks</h2>
<p>I started writing this post around 2023-03-05, so in total I've been obsessing about this specific problem for roughly seven weeks.
Initially I thought I had a much stronger result than I actually do,
so quite a bit of time was spent making sure I don't overstate the result.
In the process I've learned even more about barrier methods and self-concordant functions.</p>I was on Elossa2023-04-21T13:17:55+02:002023-04-21T13:17:55+02:00tomastag:www.härdin.se,2023-04-21:/blog/2023/04/21/i-was-on-elossa/<p><audio controls>
<source src="http://www.härdin.se/files/blog/Episode 6 Planning for Climate Change with Tomas Hardin-opus.ogg" type="audio/ogg; codecs=opus"/>
<source src="http://www.härdin.se/files/blog/Episode 6 Planning for Climate Change with Tomas Hardin.ogg" type="audio/ogg; codecs=vorbis"/>
<source src="http://www.härdin.se/files/blog/Episode 6 Planning for Climate Change with Tomas Hardin.mp3" type="audio/mpeg"/>
</audio></p>
<p>Elossa is a podcast run by <a href="https://elokapina.fi/">Elokapina</a>, the Finnish section of Extinction Rebellion.
We talk about planning, its history and especially how planning relates to the climate struggle. We also talk about the Swedish government's inability to deal with the situation.</p>
<p>Regarding XR, I am skeptical of their methods, mostly …</p><p><audio controls>
<source src="http://www.härdin.se/files/blog/Episode 6 Planning for Climate Change with Tomas Hardin-opus.ogg" type="audio/ogg; codecs=opus"/>
<source src="http://www.härdin.se/files/blog/Episode 6 Planning for Climate Change with Tomas Hardin.ogg" type="audio/ogg; codecs=vorbis"/>
<source src="http://www.härdin.se/files/blog/Episode 6 Planning for Climate Change with Tomas Hardin.mp3" type="audio/mpeg"/>
</audio></p>
<p>Elossa is a podcast run by <a href="https://elokapina.fi/">Elokapina</a>, the Finnish section of Extinction Rebellion.
We talk about planning, its history and especially how planning relates to the climate struggle. We also talk about the Swedish government's inability to deal with the situation.</p>
<p>Regarding XR, I am skeptical of their methods, mostly due to the focus on tactics to the detriment of strategy. But hey, at least they're doing something.</p>
<p>The audio is somewhat bad, I think due to transcoding to too low bitrate on Jesse's end.</p>
<ul>
<li>Download links: <a href="http://www.härdin.se/files/blog/Episode 6 Planning for Climate Change with Tomas Hardin-opus.ogg">Opus</a> (38M), <a href="http://www.härdin.se/files/blog/Episode 6 Planning for Climate Change with Tomas Hardin.ogg">Vorbis</a> (21M), <a href="http://www.härdin.se/files/blog/Episode 6 Planning for Climate Change with Tomas Hardin.mp3">MP3</a> (37M)</li>
</ul>Another reply to Josef Průša2023-04-01T15:52:35+02:002023-04-01T15:52:35+02:00tomastag:www.härdin.se,2023-04-01:/blog/2023/04/01/another-reply-to-josef-prusa/<p>Josef Průša, one of the founders of Prusa Research, recently published a post titled <a href="https://blog.prusa3d.com/the-state-of-open-source-in-3d-printing-in-2023_76659/">The state of open-source in 3D printing in 2023</a>.
In the post Průša laments the existance of cheap clones of products like the <a href="https://en.wikipedia.org/wiki/Prusa_i3">Prusa i3</a>.
A <a href="https://www.prusa3d.com/en/product/original-prusa-i3-mk3s-kit-enclosure-bundle-3/">Prusa i3 MK3 from Prusa Research in kit form</a> costs …</p><p>Josef Průša, one of the founders of Prusa Research, recently published a post titled <a href="https://blog.prusa3d.com/the-state-of-open-source-in-3d-printing-in-2023_76659/">The state of open-source in 3D printing in 2023</a>.
In the post Průša laments the existance of cheap clones of products like the <a href="https://en.wikipedia.org/wiki/Prusa_i3">Prusa i3</a>.
A <a href="https://www.prusa3d.com/en/product/original-prusa-i3-mk3s-kit-enclosure-bundle-3/">Prusa i3 MK3 from Prusa Research in kit form</a> costs 719€, whereas Chinese clones can be had for ~400€ from AliExpress.
From the point of view of users, the latter is great.
We should hope that competition manages to push the price down even further,
so long as this doesn't hurt the quality of the product or threatens workers' rights.</p>
<p>Průša cites the proliferation of cheap solar panels made in the People's Republic of China as a problem.
But the market's tendency to cheapen commodities is a historically progressive force in capitalism.
Free software and open hardware are perfectly in line with this cheapening force, a force that Průša now seeks to curtail because it threatens Prusa Research's profits.
He aims to bring this curtailment about through enclosure.
Enclosure takes many forms, but in this case the goal is to disallow "the production of nearly exact 1:1 clones for commercial purposes".
In other words Průša seeks to prevent competition.
Other fetters on the means of production are also imagined, such as banning the third party production of "obsolete" parts.</p>
<p><img alt="Darth Vader with the flag of the PRC on top and the text "I am altering the price. Pray I don't alter it any further."" src="http://www.härdin.se/images/altering.jpg"></p>
<p>A similar sentiment is echoed in the post <a href="https://blog.thea.codes/a-reply-to-josef-prusa/">A reply to Josef Průša</a> by Stargirl Flowers,
but this time in regards to Uli Behringer.
This despite Behringer engaging in the historically progressive task of cheapening audio hardware by copying other designs and manufaturing and marketing them at scale (putting aside Behringer's litigious behavior).
Stargirl calls this competition "parasitic", despite also citing the proliferation of Stratocaster clones and the benefit thereof to musicians.</p>
<p>Průša incorrectly states that "there are 1:1 clones of hardware or software on the market that do not bring anything back to the community".
But the cloners <em>do</em> bring something to the community, namely lower prices.
The real problem is that Prusa Research might go bankrupt, and thus development might slow down.
This seems unlikely since Prusa has brand recognition and many users prefer being able to get support which might not be possible with some Chinese manufaturers.
Prusa Research undoubtedly gets support calls from users who have these clones, and one way to curtail that would be to use customer numbers.
There is no reason why Prusa Research should provide support for people who are not their customers.</p>
<p>Průša is correct that the <a href="https://en.wikipedia.org/wiki/GNU_General_Public_License">GNU General Public License</a> (GPL) is not suitable for hardware.
The GPL also doesn't prohibit competition.
I cannot imagine how a license for hardware would achieve goals similar to the GPL's, since the building of software is qualitatively different from the building of hardware.
With software, building is mostly incidental to the commodity that is actually sold: developer time.
The developer's brain and the know-how contained therein cannot be replicated by any competitor.
With hardware, building results in the actual commodity that is sold.
With open hardware, all that is necessary for a competitor is given to them free of charge.</p>
<p>Another correct point is that removing attribution is bad.
It is in the interest of users to know what they are getting, to know where the schematics and source code can be had and so on.
In many cases stripping this information is illegal, and the GPL has been tested in court successfully numerous times.</p>
<p>What we have here is one part of the bourgeoisie in tension with another part of the bourgeoisie.
This tension cannot be resolved in capitalism as some commenters on Průša's post seem to think.
The only way to resolve it is socialization.
That many actors in the "open source/open hardware community" should oppose this is natural, since open source has an inherent bourgeois character.
Note that free software is not immune to similar criticism since it does not confront capitalism head on,
but it at least has the benefit that licenses like the <a href="https://en.wikipedia.org/wiki/GNU_Affero_General_Public_License">GNU Affero General Public License</a> (AGPL) are hated by companies like Google.
Contributing to AGPL projects means that the value produced does not flow into Google.</p>
<p>Stargirl makes the incorrect statement that "adoption is [Prusa Reasearch's] key metric, not revenue".
But Prusa Reasearch is a joint stock company (a.s.), and like all such companies its sole responsibility is to its shareholders and its key metric is profit.
To pretend otherwise is naïve.
Stargirl also seems to think that enclosing the electronics would not be beneficial to Prusa Research,
despite most companies doing precisely this and prospering.</p>
<p>If Josef Průša should read this then let me be clear that he is free to do as he wants. It's his company.
Prusa Research is torn between the need to satisfy its customers and its need to make profit.
As someone who is self-employed I am well aware that happy customers are repeat customers.
But I don't work for free and neither do the people at Prusa Research.
One is not in the market to be kind.
I would <em>like</em> if the Prusa i3 MK4 were also completely open, but if it isn't then I will simply spend my money elsewhere.
It is also likely that the MK4 may get Behringer'd should Prusa Research choose to keep its electronics closed,
because such closing provides incentive to people like me to design and sell open replacement boards.
Such is the market.</p>Installing libreboot on a ThinkPad T4202023-03-22T21:39:34+01:002023-03-22T21:39:34+01:00tomastag:www.härdin.se,2023-03-22:/blog/2023/03/22/installing-libreboot-on-a-thinkpad-t420/<p>In this post I have documented my efforts to get <a href="https://libreboot.org/">libreboot</a> running on a pair of Lenovo ThinkPad T420's that I found in <a href="https://umeahackerspace.se/">Umeå Hackerspace</a>.
The motivation is that I needed a new laptop, the ThinkPads were there, but they didn't support the SSD in my current laptop.
I could …</p><p>In this post I have documented my efforts to get <a href="https://libreboot.org/">libreboot</a> running on a pair of Lenovo ThinkPad T420's that I found in <a href="https://umeahackerspace.se/">Umeå Hackerspace</a>.
The motivation is that I needed a new laptop, the ThinkPads were there, but they didn't support the SSD in my current laptop.
I could of course just go and buy a new laptop, but <a href="https://en.wikipedia.org/wiki/Free_software">my precious freedoms</a>!</p>
<p>The following is based on the information on the libreboot website for the Ivybridge and Haswell (and Sandybridge) series of Intel CPUs <a href="https://libreboot.org/docs/install/ivy_has_common.html">here</a>, and the general install instructions <a href="https://libreboot.org/docs/install">here</a>.
Some inspiration has also been taken from <a href="https://www.instructables.com/Lenovo-T420-Coreboot-WRaspberry-Pi/">this</a> instructables post.
<a href="https://thinkpads.com/support/hmm/hmm_pdf/t420_t420i_hmm.pdf">The hardware manual</a> will also be of use.</p>
<p>This post is quite lengthy and some disassembly is required.
The price of freedom is eternal fiddling.</p>
<h2>Overview</h2>
<p>The process involves three major steps:</p>
<ul>
<li>Acquiring the current BIOS ROM</li>
<li>Compiling the new ROM and injecting BUP</li>
<li>Flashing the new ROM</li>
</ul>
<h2>Hardware and tools</h2>
<ul>
<li>Lenovo ThinkPad T420</li>
<li>An x86_64 machine running Debian or Ubuntu</li>
<li>Raspberry Pi Zero (or any other Pi)</li>
<li>Pomona SOIC-8 test clip</li>
<li>Six 1x1 female-female DuPont test leads</li>
<li>Screwdriver set</li>
<li>5 mm hex socket</li>
<li>Pliers</li>
<li>Tweezers</li>
<li>Thermal grease</li>
<li>Isopropanol (IPA aka 2-propanol)</li>
<li>Compressed air (actually God's gas, propane <img alt="Hank Hill" src="http://www.härdin.se/images/hank.png" style="height:2em"/>)</li>
<li>Tape</li>
</ul>
<h2>Preparing the Pi, increasing µSD life</h2>
<p>This section is a bit of a tangent, but I thought it might be useful to someone.
Here I will sumarize what preparations I did <em>before</em> doing any libreboot stuff on the Pi.</p>
<p>Whenever you boot a Raspberry Pi for the first time it will ask for things like the WiFi password.
It will also attempt to upgrade all packages installed, which in my case didn't work automatically.
Instead I had to do it manually, roughly like so:</p>
<div class="highlight"><pre><span></span><code>pi@pizero0:~<span class="w"> </span>$<span class="w"> </span>sudo<span class="w"> </span>apt<span class="w"> </span>update<span class="w"> </span><span class="o">&&</span><span class="w"> </span>sudo<span class="w"> </span>apt<span class="w"> </span>upgrade<span class="w"> </span>--yes<span class="w"> </span><span class="o">&&</span><span class="w"> </span>sudo<span class="w"> </span>apt<span class="w"> </span>dist-upgrade<span class="w"> </span>--yes
</code></pre></div>
<p>This takes a while.
The reason for this is that Debian Buster is now oldstable rather than stable.
I went for coffee at a local book shop while it was running.</p>
<p>I also set the Pi up to log to RAM, to put temporary files also in RAM, and I disabled the swap.
This in order to prolong the life of its µSD card.</p>
<div class="highlight"><pre><span></span><code>pi@pizero0:~<span class="w"> </span>$<span class="w"> </span>cat<span class="w"> </span><span class="s"><<EOF | sudo bash -c "cat >> /etc/fstab"</span>
<span class="s">tmpfs /tmp tmpfs defaults,noatime,nosuid 0 0</span>
<span class="s">tmpfs /var/log tmpfs defaults,noatime,nosuid,size=16M 0 0</span>
<span class="s">EOF</span>
pi@pizero0:~<span class="w"> </span>$<span class="w"> </span>sudo<span class="w"> </span>apt<span class="w"> </span>remove<span class="w"> </span>--yes<span class="w"> </span>dphys-swapfile
</code></pre></div>
<p>Jonasbits helpfully informed me that <a href="https://dietpi.com/">DietPi</a> exists which would likely be helpful here.
For now I use the stock NOOBS.</p>
<h2>Acquiring the existing ROM</h2>
<p>Reading the BIOS ROM involves these steps:</p>
<ul>
<li>Compiling <code>flashrom</code> on the Pi</li>
<li>Disassembling the T420</li>
<li>Connecting the SOIC-8 test clip and reading the ROM</li>
</ul>
<h3>Setting up flashrom on the Raspberry Pi</h3>
<p>Use the Raspberry Pi configuration tool to enable SSH and SPI.
Make sure you can SSH into the Pi, because having to use a second screen can be annoying.
Also make sure the device <code>/dev/spidev0.0</code> exists. Reboot.</p>
<p>SSH into the Pi and follow the instructions <a href="https://libreboot.org/docs/install/spi.html">here</a> for installing <code>flashrom</code>:</p>
<div class="highlight"><pre><span></span><code>pi@pizero0:~<span class="w"> </span>$<span class="w"> </span>git<span class="w"> </span>clone<span class="w"> </span>https://notabug.org/libreboot/lbmk<span class="w"> </span>
pi@pizero0:~<span class="w"> </span>$<span class="w"> </span><span class="nb">cd</span><span class="w"> </span>lbmk/
pi@pizero0:~/lbmk<span class="w"> </span>$<span class="w"> </span>sudo<span class="w"> </span>./build<span class="w"> </span>dependencies<span class="w"> </span>ubuntu2004
pi@pizero0:~/lbmk<span class="w"> </span>$<span class="w"> </span>./download<span class="w"> </span>flashrom
pi@pizero0:~/lbmk<span class="w"> </span>$<span class="w"> </span>./build<span class="w"> </span>module<span class="w"> </span>flashrom
</code></pre></div>
<h3>Disassembling the T420</h3>
<p>Get your tools out!</p>
<p><a href="http://www.härdin.se/images/libreboot/IMG_20230315_143925.jpg"><img alt="T420 motherboard" src="http://www.härdin.se/images/libreboot/tIMG_20230315_143925.jpg"></a></p>
<p>Disassemble the T420 per <a href="https://thinkpads.com/support/hmm/hmm_pdf/t420_t420i_hmm.pdf">the hardware manual</a>.
Follow in particular the section "1200 Magnesium structure frame" on page 110.
It in turn points to these sections, to be done in the order given:</p>
<ul>
<li>“1010 Battery pack” on page 67</li>
<li>“1020 ExpressCard blank bezel” on page 68</li>
<li>“1030 Serial Ultrabay Enhanced device or travel bezel” on page 69</li>
<li>“1040 Hard disk drive (HDD) and solid state drive (SSD)” on page 70</li>
<li>“1050 DIMM slot cover” on page 73</li>
<li>“1070 PCI Express Mini Card for wireless WAN” on page 75</li>
<li>“1080 Keyboard” on page 77</li>
<li>“1110 PCI Express Mini Card for wireless LAN” on page 85</li>
<li>“1120 Keyboard bezel assembly, FPC cable, and Bluethooth daughter card” on page 87</li>
<li>“1150 Speaker assembly” on page 95</li>
<li>“1160 LCD unit” on page 97</li>
<li>“1170 Fan assembly” on page 101</li>
<li>“1180 CPU” on page 105</li>
<li>“1190 Base cover assembly and DC-in connector cable” on page 106</li>
</ul>
<p>I could not figure out how to remove the SmartCard reader, but luckily disconnecting it is enough.</p>
<p><a href="http://www.härdin.se/images/libreboot/IMG_20230315_144025.jpg"><img alt="Location of ROM" src="http://www.härdin.se/images/libreboot/tIMG_20230315_144025.jpg"></a></p>
<p>Locate the ROM chip. Its part number is <a href="https://media.digikey.com/pdf/Data%20Sheets/Winbond%20PDFs/W25Q64CV.pdf">Winbond 25Q64CVSFIG</a> (SOIC-8 208-mil variant, 32nd week of 2012).
Note that the T420 only has one chip, not two chips like other Ivybridge/Haswell machines might have (<a href="https://libreboot.org/docs/install/#target-thinkpad-x220t420t420s">libreboot's install instructions agree on this</a>).</p>
<p>While you have everything disassembled, give things some compressed air blasts to get rid of dust, especially in and around the cooling fan.
Don't overdo it though, fans deal poorly with infinite RPMs.</p>
<h3>Reading the ROM</h3>
<p>First wire up the SOIC test clip to the Pi.
The table and picture below hopefully shows how to do this clearly enough:</p>
<table>
<tr><th>Name</th><th>Color</th><th>Test clip pin#</th><th>Pi pin#</th></tr>
<tr><td>/CS</td><td>brown</td><td>1</td><td>24</td></tr>
<tr><td>MISO (DO)</td><td>yellow</td><td>2</td><td>21</td></tr>
<tr><td>GND</td><td>black</td><td>4</td><td>6</td></tr>
<tr><td>MOSI (DI)</td><td>orange</td><td>5</td><td>19</td></tr>
<tr><td>SCLK (CLK)</td><td>green</td><td>6</td><td>23</td></tr>
<tr><td>VCC</td><td>red</td><td>8</td><td>1</td></tr>
</table>
<p>This picture in particular is exactly how I connected the two:</p>
<p><a href="http://www.härdin.se/images/libreboot/IMG_20230315_160745.jpg"><img alt="SOIC test clip connections" src="http://www.härdin.se/images/libreboot/tIMG_20230315_160745.jpg"></a></p>
<p>Before attaching the clip to the motherboard, make sure the Pi is not connected to power.
The connect the test clip as shown in the picture below.</p>
<p><a href="http://www.härdin.se/images/libreboot/IMG_20230315_161008.jpg"><img alt="SOIC location" src="http://www.härdin.se/images/libreboot/tIMG_20230315_161008.jpg"></a></p>
<p>MAKE SURE THE ORIENTATION OF THE TEST CLIP IS CORRECT OR YOU WILL LIKELY FRY THE MOTHERBOARD.
The VCC pin is in the upper right corner, opposite the indentation on the package.
The indentation indicates pin 1, and IC pins are counted counterclockwise.
This is a holdover from the vacuum tube days.
Pin 8 is therefore the top-right pin.
GND is the bottom-left.</p>
<p>After this, connect power to the Pi.
SSH into the Pi and probe the ROM using flashrom:</p>
<div class="highlight"><pre><span></span><code>pi@pizero0:~<span class="w"> </span>$<span class="w"> </span>sudo<span class="w"> </span>flashrom<span class="w"> </span>-p<span class="w"> </span>linux_spi:dev<span class="o">=</span>/dev/spidev0.0,spispeed<span class="o">=</span><span class="m">32768</span>
flashrom<span class="w"> </span>on<span class="w"> </span>Linux<span class="w"> </span><span class="m">5</span>.10.103+<span class="w"> </span><span class="o">(</span>armv6l<span class="o">)</span>
flashrom<span class="w"> </span>is<span class="w"> </span>free<span class="w"> </span>software,<span class="w"> </span>get<span class="w"> </span>the<span class="w"> </span><span class="nb">source</span><span class="w"> </span>code<span class="w"> </span>at<span class="w"> </span>https://flashrom.org
Using<span class="w"> </span>clock_gettime<span class="w"> </span><span class="k">for</span><span class="w"> </span>delay<span class="w"> </span>loops<span class="w"> </span><span class="o">(</span>clk_id:<span class="w"> </span><span class="m">1</span>,<span class="w"> </span>resolution:<span class="w"> </span>1ns<span class="o">)</span>.
Found<span class="w"> </span>Winbond<span class="w"> </span>flash<span class="w"> </span>chip<span class="w"> </span><span class="s2">"W25Q64.V"</span><span class="w"> </span><span class="o">(</span><span class="m">8192</span><span class="w"> </span>kB,<span class="w"> </span>SPI<span class="o">)</span><span class="w"> </span>on<span class="w"> </span>linux_spi.
No<span class="w"> </span>operations<span class="w"> </span>were<span class="w"> </span>specified.
</code></pre></div>
<p><code>flashrom</code> successfully identified the chip.
Dump the ROM:</p>
<div class="highlight"><pre><span></span><code>pi@pizero0:~<span class="w"> </span>$<span class="w"> </span>sudo<span class="w"> </span>flashrom<span class="w"> </span>-p<span class="w"> </span>linux_spi:dev<span class="o">=</span>/dev/spidev0.0,spispeed<span class="o">=</span><span class="m">32768</span><span class="w"> </span>-r<span class="w"> </span>dump.bin
</code></pre></div>
<p>I ran four more dumps using a bash loop like so:</p>
<div class="highlight"><pre><span></span><code>pi@pizero0:~<span class="w"> </span>$<span class="w"> </span><span class="k">for</span><span class="w"> </span>x<span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="k">$(</span>seq<span class="w"> </span><span class="m">1</span><span class="w"> </span><span class="m">4</span><span class="k">)</span><span class="p">;</span><span class="w"> </span><span class="k">do</span><span class="w"> </span>sudo<span class="w"> </span>flashrom<span class="w"> </span>-p<span class="w"> </span>linux_spi:dev<span class="o">=</span>/dev/spidev0.0,spispeed<span class="o">=</span><span class="m">32768</span><span class="w"> </span>-r<span class="w"> </span>dump<span class="nv">$x</span>.bin<span class="w"> </span><span class="p">;</span><span class="k">done</span>
</code></pre></div>
<p>Use <code>sha1sum</code> to verify that they're all the same:</p>
<div class="highlight"><pre><span></span><code>pi@pizero0:~<span class="w"> </span>$<span class="w"> </span>sha1sum<span class="w"> </span>*.bin
d92c6217cb7dbc3e8cf5bbd1cd59ade4b10aef4e<span class="w"> </span>dump1.bin
d92c6217cb7dbc3e8cf5bbd1cd59ade4b10aef4e<span class="w"> </span>dump2.bin
d92c6217cb7dbc3e8cf5bbd1cd59ade4b10aef4e<span class="w"> </span>dump3.bin
d92c6217cb7dbc3e8cf5bbd1cd59ade4b10aef4e<span class="w"> </span>dump4.bin
d92c6217cb7dbc3e8cf5bbd1cd59ade4b10aef4e<span class="w"> </span>dump.bin
</code></pre></div>
<p>A dump of another T420 had the SHA-1 hash 4f006fff0a1e7e2613e15dbb452b7009d19d00e6, so ROMs are definitely different across laptops.
I renamed <code>blob.bin</code> to <code>t420.bin</code> after this.
Finally copy <code>t420.bin</code> to your main machine using for example <code>scp</code>.</p>
<h2>Building the new BIOS ROM</h2>
<p>In order for libreboot's <code>lbmk</code> to be able to do its thing you will need to use Debian sid or similar.
Since I didn't want to bring my machine to a potentially unstable state I decided to make use of <a href="https://www.docker.com/">docker</a> instead.</p>
<p>On the x86 machine, in the same directory that you have <code>t420.bin</code> paste the following into a file called <code>Dockerfile</code>:</p>
<div class="highlight"><pre><span></span><code><span class="k">FROM</span><span class="w"> </span><span class="s">debian:sid</span>
<span class="k">RUN</span><span class="w"> </span>apt<span class="w"> </span>update
<span class="k">RUN</span><span class="w"> </span>apt<span class="w"> </span>install<span class="w"> </span>--yes<span class="w"> </span>gettext<span class="w"> </span>git
<span class="k">RUN</span><span class="w"> </span>git<span class="w"> </span>clone<span class="w"> </span>https://notabug.org/libreboot/lbmk
<span class="k">WORKDIR</span><span class="w"> </span><span class="s">/lbmk</span>
<span class="k">RUN</span><span class="w"> </span>./build<span class="w"> </span>dependencies<span class="w"> </span>debian
<span class="k">RUN</span><span class="w"> </span>git<span class="w"> </span>config<span class="w"> </span>--global<span class="w"> </span>user.email<span class="w"> </span><span class="s2">""</span>
<span class="k">RUN</span><span class="w"> </span>git<span class="w"> </span>config<span class="w"> </span>--global<span class="w"> </span>user.name<span class="w"> </span><span class="s2">"root"</span>
<span class="k">COPY</span><span class="w"> </span>t420.bin<span class="w"> </span>/lbmk
<span class="k">RUN</span><span class="w"> </span>./blobutil<span class="w"> </span>extract<span class="w"> </span>t420_8mb<span class="w"> </span>t420.bin
<span class="k">RUN</span><span class="w"> </span>./build<span class="w"> </span>boot<span class="w"> </span>roms<span class="w"> </span>t420_8mb
<span class="k">RUN</span><span class="w"> </span><span class="k">for</span><span class="w"> </span>f<span class="w"> </span><span class="k">in</span><span class="w"> </span>bin/t420_8mb/*.rom<span class="p">;</span><span class="w"> </span><span class="k">do</span><span class="w"> </span>./blobutil<span class="w"> </span>inject<span class="w"> </span>-r<span class="w"> </span><span class="nv">$f</span><span class="w"> </span>-b<span class="w"> </span>t420_8mb<span class="p">;</span><span class="w"> </span><span class="k">done</span>
</code></pre></div>
<p>Apart from building a bunch of ROMs this will also inject the one disgusting but unfortunately necessary Intel ME blob, BUP (bringup), taken from <code>t420.bin</code>.
The gettext install may currently (as of <code>f9e20b8a1d93dec3b6389ca9a7575765c9cc733d</code>) be necessary due to some kind of change in Debian.
This issue has been fixed as of the commit after that (<code>ebd9ec96c464d73e5667acf0a0735afec10e961a</code>) but some readers may be using older lbmk's.</p>
<p>Moving on, to build the ROMs and copy them out of docker run the following:</p>
<div class="highlight"><pre><span></span><code>docker<span class="w"> </span>build<span class="w"> </span>-t<span class="w"> </span>t420<span class="w"> </span>-f<span class="w"> </span>Dockerfile<span class="w"> </span>.
<span class="nv">ID</span><span class="o">=</span><span class="k">$(</span>docker<span class="w"> </span>create<span class="w"> </span>t420<span class="k">)</span>
docker<span class="w"> </span>cp<span class="w"> </span><span class="nv">$ID</span>:/lbmk/bin/t420_8mb<span class="w"> </span>.
docker<span class="w"> </span>rm<span class="w"> </span><span class="nv">$ID</span>
</code></pre></div>
<p>After quite some time (50 minutes on my machine) this will create a directory <code>t420_8mb</code> with the following files inside:</p>
<ul>
<li>grub_t420_8mb_libgfxinit_corebootfb_colemak.rom</li>
<li>grub_t420_8mb_libgfxinit_corebootfb_deqwertz.rom</li>
<li>grub_t420_8mb_libgfxinit_corebootfb_esqwerty.rom</li>
<li>grub_t420_8mb_libgfxinit_corebootfb_frazerty.rom</li>
<li>grub_t420_8mb_libgfxinit_corebootfb_frdvbepo.rom</li>
<li>grub_t420_8mb_libgfxinit_corebootfb_itqwerty.rom</li>
<li>grub_t420_8mb_libgfxinit_corebootfb_svenska.rom</li>
<li>grub_t420_8mb_libgfxinit_corebootfb_trqwerty.rom</li>
<li>grub_t420_8mb_libgfxinit_corebootfb_ukdvorak.rom</li>
<li>grub_t420_8mb_libgfxinit_corebootfb_ukqwerty.rom</li>
<li>grub_t420_8mb_libgfxinit_corebootfb_usdvorak.rom</li>
<li>grub_t420_8mb_libgfxinit_corebootfb_usqwerty.rom</li>
<li>seabios_withgrub_t420_8mb_libgfxinit_corebootfb_colemak.rom</li>
<li>seabios_withgrub_t420_8mb_libgfxinit_corebootfb_deqwertz.rom</li>
<li>seabios_withgrub_t420_8mb_libgfxinit_corebootfb_esqwerty.rom</li>
<li>seabios_withgrub_t420_8mb_libgfxinit_corebootfb_frazerty.rom</li>
<li>seabios_withgrub_t420_8mb_libgfxinit_corebootfb_frdvbepo.rom</li>
<li>seabios_withgrub_t420_8mb_libgfxinit_corebootfb_itqwerty.rom</li>
<li>seabios_withgrub_t420_8mb_libgfxinit_corebootfb_svenska.rom</li>
<li>seabios_withgrub_t420_8mb_libgfxinit_corebootfb_trqwerty.rom</li>
<li>seabios_withgrub_t420_8mb_libgfxinit_corebootfb_ukdvorak.rom</li>
<li>seabios_withgrub_t420_8mb_libgfxinit_corebootfb_ukqwerty.rom</li>
<li>seabios_withgrub_t420_8mb_libgfxinit_corebootfb_usdvorak.rom</li>
<li>seabios_withgrub_t420_8mb_libgfxinit_corebootfb_usqwerty.rom</li>
</ul>
<p>I used <code>seabios_withgrub_t420_8mb_libgfxinit_corebootfb_svenska.rom</code>.</p>
<h3>Flashing the new ROM</h3>
<p>Re-attach the test clip, again BEING CAREFUL THAT IT IS IN THE RIGHT ORIENTATION.
Test that the connection is good:</p>
<div class="highlight"><pre><span></span><code>pi@pizero0:~<span class="w"> </span>$<span class="w"> </span>sudo<span class="w"> </span>flashrom<span class="w"> </span>-p<span class="w"> </span>linux_spi:dev<span class="o">=</span>/dev/spidev0.0,spispeed<span class="o">=</span><span class="m">32768</span>
flashrom<span class="w"> </span>on<span class="w"> </span>Linux<span class="w"> </span><span class="m">5</span>.10.103+<span class="w"> </span><span class="o">(</span>armv6l<span class="o">)</span>
flashrom<span class="w"> </span>is<span class="w"> </span>free<span class="w"> </span>software,<span class="w"> </span>get<span class="w"> </span>the<span class="w"> </span><span class="nb">source</span><span class="w"> </span>code<span class="w"> </span>at<span class="w"> </span>https://flashrom.org
Using<span class="w"> </span>clock_gettime<span class="w"> </span><span class="k">for</span><span class="w"> </span>delay<span class="w"> </span>loops<span class="w"> </span><span class="o">(</span>clk_id:<span class="w"> </span><span class="m">1</span>,<span class="w"> </span>resolution:<span class="w"> </span>1ns<span class="o">)</span>.
Found<span class="w"> </span>Winbond<span class="w"> </span>flash<span class="w"> </span>chip<span class="w"> </span><span class="s2">"W25Q64.V"</span><span class="w"> </span><span class="o">(</span><span class="m">8192</span><span class="w"> </span>kB,<span class="w"> </span>SPI<span class="o">)</span><span class="w"> </span>on<span class="w"> </span>linux_spi.
No<span class="w"> </span>operations<span class="w"> </span>were<span class="w"> </span>specified.
</code></pre></div>
<p>Finally flash your desired ROM:</p>
<div class="highlight"><pre><span></span><code>pi@pizero0:~<span class="w"> </span>$<span class="w"> </span>sudo<span class="w"> </span>flashrom<span class="w"> </span>-p<span class="w"> </span>linux_spi:dev<span class="o">=</span>/dev/spidev0.0,spispeed<span class="o">=</span><span class="m">32768</span><span class="w"> </span>-w<span class="w"> </span>seabios_withgrub_t420_8mb_libgfxinit_corebootfb_svenska.rom<span class="w"> </span>
flashrom<span class="w"> </span>on<span class="w"> </span>Linux<span class="w"> </span><span class="m">5</span>.10.103+<span class="w"> </span><span class="o">(</span>armv6l<span class="o">)</span>
flashrom<span class="w"> </span>is<span class="w"> </span>free<span class="w"> </span>software,<span class="w"> </span>get<span class="w"> </span>the<span class="w"> </span><span class="nb">source</span><span class="w"> </span>code<span class="w"> </span>at<span class="w"> </span>https://flashrom.org
Using<span class="w"> </span>clock_gettime<span class="w"> </span><span class="k">for</span><span class="w"> </span>delay<span class="w"> </span>loops<span class="w"> </span><span class="o">(</span>clk_id:<span class="w"> </span><span class="m">1</span>,<span class="w"> </span>resolution:<span class="w"> </span>1ns<span class="o">)</span>.
Found<span class="w"> </span>Winbond<span class="w"> </span>flash<span class="w"> </span>chip<span class="w"> </span><span class="s2">"W25Q64.V"</span><span class="w"> </span><span class="o">(</span><span class="m">8192</span><span class="w"> </span>kB,<span class="w"> </span>SPI<span class="o">)</span><span class="w"> </span>on<span class="w"> </span>linux_spi.
Reading<span class="w"> </span>old<span class="w"> </span>flash<span class="w"> </span>chip<span class="w"> </span>contents...<span class="w"> </span><span class="k">done</span>.
Erasing<span class="w"> </span>and<span class="w"> </span>writing<span class="w"> </span>flash<span class="w"> </span>chip...<span class="w"> </span>Erase/write<span class="w"> </span><span class="k">done</span>.
Verifying<span class="w"> </span>flash...<span class="w"> </span>VERIFIED.
</code></pre></div>
<p>Even though <code>flashrom</code> says that it verified the ROM I wanted to be extra sure:</p>
<div class="highlight"><pre><span></span><code>pi@pizero0:~<span class="w"> </span>$<span class="w"> </span>sudo<span class="w"> </span>flashrom<span class="w"> </span>-p<span class="w"> </span>linux_spi:dev<span class="o">=</span>/dev/spidev0.0,spispeed<span class="o">=</span><span class="m">32768</span><span class="w"> </span>-r<span class="w"> </span>read.bin
flashrom<span class="w"> </span>on<span class="w"> </span>Linux<span class="w"> </span><span class="m">5</span>.10.103+<span class="w"> </span><span class="o">(</span>armv6l<span class="o">)</span>
flashrom<span class="w"> </span>is<span class="w"> </span>free<span class="w"> </span>software,<span class="w"> </span>get<span class="w"> </span>the<span class="w"> </span><span class="nb">source</span><span class="w"> </span>code<span class="w"> </span>at<span class="w"> </span>https://flashrom.org
Using<span class="w"> </span>clock_gettime<span class="w"> </span><span class="k">for</span><span class="w"> </span>delay<span class="w"> </span>loops<span class="w"> </span><span class="o">(</span>clk_id:<span class="w"> </span><span class="m">1</span>,<span class="w"> </span>resolution:<span class="w"> </span>1ns<span class="o">)</span>.
Found<span class="w"> </span>Winbond<span class="w"> </span>flash<span class="w"> </span>chip<span class="w"> </span><span class="s2">"W25Q64.V"</span><span class="w"> </span><span class="o">(</span><span class="m">8192</span><span class="w"> </span>kB,<span class="w"> </span>SPI<span class="o">)</span><span class="w"> </span>on<span class="w"> </span>linux_spi.
Reading<span class="w"> </span>flash...<span class="w"> </span><span class="k">done</span>.
pi@pizero0:~<span class="w"> </span>$<span class="w"> </span>sha1sum<span class="w"> </span>seabios_withgrub_t420_8mb_libgfxinit_corebootfb_svenska.rom<span class="w"> </span>read.bin<span class="w"> </span>
e62ee26ab046d567004b907ba1950e819b60d252<span class="w"> </span>seabios_withgrub_t420_8mb_libgfxinit_corebootfb_svenska.rom
e62ee26ab046d567004b907ba1950e819b60d252<span class="w"> </span>read.bin
</code></pre></div>
<p>Congratulations! Your T420 is now librebooted!</p>
<p>At this point it may be useful to solder some thin wires to the programming header next to the BIOS ROM and making them accessible via the DIMM slot cover.
I didn't end up doing this, but readers who plan on flashing many times may want to do so to save on having to disassemble more than once.</p>
<p>Now the only thing left to do is reassemble the T420. Remember to apply new thermal compound, and remember to re-enable the WiFi by sliding the kill switch on the right edge forward.
I forgot this last step and was very confused why my WiFi wasn't working 😑
I also had an issue with the my second 8 GiB DDR3 stick not being detected, but reseating it fixed that issue.</p>
<p>I did the same procedure to a second T420 and it seems to have worked mostly fine.
There is some kind of issue with SeaBIOS not being able to boot from its drive, but telling SeaBIOS to start grub instead allows booting.
I'm not sure why. Might have something to do with how Debian was installed on that machine. Oh well.</p>I was on The Deprogram!2023-03-13T12:10:38+01:002023-03-13T12:10:38+01:00tomastag:www.härdin.se,2023-03-13:/blog/2023/03/13/i-was-on-the-deprogram/<p><audio controls>
<source src="http://www.härdin.se/files/blog/12413758-episode-69-gosplanning-industrial-funko-pop-production-ft-tomas-hardin-opus.ogg" type="audio/ogg; codecs=opus"/>
<source src="http://www.härdin.se/files/blog/12413758-episode-69-gosplanning-industrial-funko-pop-production-ft-tomas-hardin.ogg" type="audio/ogg; codecs=vorbis"/>
<source src="http://www.härdin.se/files/blog/12413758-episode-69-gosplanning-industrial-funko-pop-production-ft-tomas-hardin.mp3" type="audio/mpeg"/>
</audio></p>
<p>The Deprogram is a podcast run by the YouTubers Hakim, Yugopnik and Second Thought (aka JT) that talks about socialist theory, with jokes.</p>
<p>Hopefully I got the <audio> element above correct. Your browser should prefer Opus, then Vorbis, and finally fall back on MP3. In Firefox seeking in MP3 doesn't …</p><p><audio controls>
<source src="http://www.härdin.se/files/blog/12413758-episode-69-gosplanning-industrial-funko-pop-production-ft-tomas-hardin-opus.ogg" type="audio/ogg; codecs=opus"/>
<source src="http://www.härdin.se/files/blog/12413758-episode-69-gosplanning-industrial-funko-pop-production-ft-tomas-hardin.ogg" type="audio/ogg; codecs=vorbis"/>
<source src="http://www.härdin.se/files/blog/12413758-episode-69-gosplanning-industrial-funko-pop-production-ft-tomas-hardin.mp3" type="audio/mpeg"/>
</audio></p>
<p>The Deprogram is a podcast run by the YouTubers Hakim, Yugopnik and Second Thought (aka JT) that talks about socialist theory, with jokes.</p>
<p>Hopefully I got the <audio> element above correct. Your browser should prefer Opus, then Vorbis, and finally fall back on MP3. In Firefox seeking in MP3 doesn't seem to work, while both Opus and Vorbis work fine. This is because unlike MP3, Opus and Vorbis use the Ogg container which works fine in this case <a href="https://hardwarebug.org/2010/03/03/ogg-objections/">despite its many problems</a>.</p>
<ul>
<li>Download links: <a href="http://www.härdin.se/files/blog/12413758-episode-69-gosplanning-industrial-funko-pop-production-ft-tomas-hardin-opus.ogg">Opus</a> (38M), <a href="http://www.härdin.se/files/blog/12413758-episode-69-gosplanning-industrial-funko-pop-production-ft-tomas-hardin.ogg">Vorbis</a> (36M), <a href="http://www.härdin.se/files/blog/12413758-episode-69-gosplanning-industrial-funko-pop-production-ft-tomas-hardin.mp3">MP3</a> (53M)</li>
<li><a href="https://www.reddit.com/r/TheDeprogram/comments/11ns0uv/episode_69_gosplanning_industrial_funko_pop/.compact">Relevant post on the /r/TheDeprogram subreddit</a></li>
<li><a href="https://www.youtube.com/watch?v=A6hGN_Gg32M">YouTube version</a> (<a href="https://vid.puffyan.us/watch?v=A6hGN_Gg32M">invidious link</a>)</li>
</ul>Feasibility is optimal2023-02-26T21:17:20+01:002023-02-26T21:17:20+01:00tomastag:www.härdin.se,2023-02-26:/blog/2023/02/26/feasibility-is-optimal/<p>In this post I will critique some points I have made in favor of optimality.
Examples can be seen <a href="http://www.härdin.se/blog/2021/02/24/planning-complexity-for-model-economies/">here</a> and <a href="http://www.härdin.se/blog/2022/02/04/towards-large-scale-linear-planning/">here</a>.</p>
<p>In the literature and present discourse on calculation in kind there is much debate around optimization.
Leonid Kantorovich's "plan rays" is the start of this discussion as far …</p><p>In this post I will critique some points I have made in favor of optimality.
Examples can be seen <a href="http://www.härdin.se/blog/2021/02/24/planning-complexity-for-model-economies/">here</a> and <a href="http://www.härdin.se/blog/2022/02/04/towards-large-scale-linear-planning/">here</a>.</p>
<p>In the literature and present discourse on calculation in kind there is much debate around optimization.
Leonid Kantorovich's "plan rays" is the start of this discussion as far as I can tell.
They get picked up again by Paul Cockshott and Allin Cottrell in <em>Towards a New Socialism</em>, and more recently by Phillip Dapprich.
I have suggested optimizing on labour, for example <a href="http://www.härdin.se/blog/2021/02/08/some-example-economic-linear-programs/">here</a>.
More recently in our <a href="http://www.härdin.se/blog/2022/12/20/marx22-presentation-video/">Marx22 presentation</a> me and Dave Zachariah have suggested that different regions might optimize on different things.
But there are some problems with these notions of optimization.</p>
<h2>Bad data</h2>
<p>A major problem with pushing too hard for "optimal" plans is that they depend on the quality of the data.
Whatever you have in your database is only ever an approximation of reality.
The map is not the terrain.</p>
<p>In real systems with humans in the loop there will inevitably be incorrect data entered either by accident or deliberately in order to game the system.
These situations can to some extent be detected using statistics, but it's never perfect.</p>
<p>Incorrect data directly results in incorrect constraints, which in turn may result in plans that cannot be satisfied in the real world.
Assuming perfect data therefore threatens viability.</p>
<p>Unexpected things may also happen, and if the currently computed plan is too close to a constraint that is affected by such events then it will be more difficult to plan around them.
A concrete example could be a solver that optimizes on labour choosing to centralize distribution in a continent to a single location because it is more economic in terms of labour to do so.
As soon as such a distribution hub is hit by a disaster the problem with that approach will quickly become apparent.</p>
<p>Graphically these situations look something like this:</p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/against_optimality/extreme.svg" alt="An ill-conditioned linear program represented by a very acute triangle with an X near the tip"/></p>
<p>We are optimizing in the direction of <math>
<mi>c</mi>
</math> and <span style="color:#e82626ff;font-weight:bold">x</span> marks the current plan, quite close to optimum.
The sides <em>E</em> and <em>F</em> of the triangle form an acute angle.
In a situation like this the linear program that the triangle <em>DEF</em> represents is called <em>ill-conditioned</em>.
A small change to the system may cause a large change in the solution.</p>
<p>Suppose that <em>E</em> is is disturbed for some reason such that its angle relative to <em>D</em> decreases.
In that case we will get a situation like this:</p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/against_optimality/extreme2.svg" alt="The new linear program with the X moved a large distance"/></p>
<p>In order for the plan to still be viable it has to be updated so that it sits in the triangle <em>DE'F</em>.
It should be apparent that this requires that the plan changes considerably.</p>
<h2>Stay in the middle (or: Keep these constraints away from me!)</h2>
<p>If the corners are dangerous then the thought arises that perhaps it is best if we stay as far away from them as possible?
One way to achieve this is to stay as far away from any constraint as possible.
This is an idea central to so-called barrier methods for linear programming.</p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/against_optimality/interior.svg" alt="The triangle is filled with an elliptic gradient. The X sits in the center of the gradient towards the short side D"/></p>
<p>A function is defined that for each point in the triangle expresses how far it is from all constraints.
This function can be defined such that there is one and only one point in the system that is the "furthest" away from all constraints.
This point is known as the <em>centroid</em> of the system.
The mathematics of this is elaborated on further down.</p>
<p>Suppose the same thing happens to this system, namely that the angle between <em>D</em> and <em>E</em> decreases:</p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/against_optimality/interior2.svg" alt="A similar situation as last time, except X has to move much less"/></p>
<p>The solution will have to move much less in this case in order to reach its desired position.
Our ill-conditioned system is suddenly well-conditioned.
In practical terms this may mean that the solver deliberately chooses to spread goods out a bit in order to have sufficient leeway.
This leeway also has political implications.
It allows for greater autonomy in workplaces without this imposing huge hanges to the overall plan.
Local <em>variety</em> thereby gets attenuated.</p>
<p>The middle is good. The middle is safe.</p>
<h2>Computational aspects</h2>
<p>One practical reason to reconsider optimality is the computational cost of it.
Due to Nesterov and Todd it is known that barrier methods for solving convex programming require at most <math>
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>L</mi><msqrt><mi>m</mi></msqrt><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> Newton steps for <math>
<mi>L</mi>
</math> bits of accuracy.
Todd and Ye have shown that the problem requires <math>
<mrow><mi mathvariant="normal">Ω</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>L</mi><mroot><mi>m</mi><mn>3</mn></mroot><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> Newton steps for some (not all) programs when using predictor-corrector methods.
In other words convex programming cannot be guaranteed to require fewer Newton steps than somewhere between the cube root and square root of the number of constraints, times some constant, times the desired digits of accuracy.
In practice the problem is easier than this,
but it is also much more difficult than the point I am getting to.</p>
<p>If we abandon optimality for a moment and take from barrier methods only the concept of centrality,
then we'll have reduced the required computations immensely.
This means we can offer faster feedback to users.
To see why this is the case it is necessary to know that barrier methods rely on Newton iteration, which has quadratic convergence near the solution.
This means that after each iteration the number of digits that are correct <em>doubles</em>.</p>
<p>One key question is what is meant by being "near" the solution.
Renegar shows that it is possible to move a constraint at least <math>
<mrow><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>13</mn><msqrt><mi>m</mi></msqrt></mrow>
</math> of the way toward the current center of the system and that one needs only a single Newton step to re-center in the new system.
With <math>
<mrow><mi>m</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>46</mn><mo lspace="0.222em" rspace="0.222em">*</mo><msup><mn>10</mn><mn>9</mn></msup></mrow>
</math> this is quite a short distance, less than one millionth.
In practice it is possible to move the constraints much further at the cost of more Newton iterations.
But it is also known that for some programs performing such aggressive updates will yield Newton steps that end up outside the feasible region.</p>
<p>In a draft version of this text I had an estimate what the required computations will have shrunk to (3¼ hours),
but after re-reading Renegar I realized that estimate was too optimistic.
For planning it may still be valid, but I prefer more guarded language.</p>
<h2>In favor of optimality</h2>
<p>Now that I have spilled some ink critiquing optimality in favor of centrality,
why is the title of this section pro-optimality?
The reason is because the above amounts to optimizing on feasibility.</p>
<p>Barrier methods approach finding the solution that maximizes <math>
<mrow><msup><mi>c</mi><mi>T</mi></msup><mspace width="0"/><mi>x</mi></mrow>
</math> by defining a barrier function <math>
<mrow><mi>f</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>x</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> that quantifies "how far" <math>
<mi>x</mi>
</math> is from all constraints in the system <math>
<mrow><mi>A</mi><mspace width="0"/><mi>x</mi><mo lspace="0.278em" rspace="0.278em">≥</mo><mi>b</mi></mrow>
</math>.
It looks as follows:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>f</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>x</mi><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">=</mo><msub><mo lspace="0" rspace="0.167em" stretchy="false">∑</mo><mi>i</mi></msub><mi>log</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup><mspace width="0"/><mi>x</mi><mo lspace="0.222em" rspace="0.222em">-</mo><msub><mi>b</mi><mi>i</mi></msub><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math>
</span></p>
<p>where <math>
<msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup>
</math> is each row in <math>
<mi>A</mi>
</math>.</p>
<p>Renegar shows that <math>
<mrow><mi>f</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>x</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> is upward convex (strictly concave), and because of this there exists a unique solution that maximizes <math>
<mrow><mi>f</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>x</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> which Renegar calls <math>
<mi>ξ</mi>
</math>.</p>
<!-- Renegar further shows that the Newton method always converges so long as <math>
<mrow><mi>δ</mi><mo lspace="0.278em" rspace="0.278em"><</mo><mi>f</mi><mspace width="0"/><mi>o</mi><mspace width="0"/><mi>o</mi></mrow>
</math> -->
<p>If one has a measure of uncertainty associated with each constraint then the system can be rescaled such that the optimal solution <math>
<mi>ξ</mi>
</math> is the one that maximizes certainty.
I consider such certainty maximization to be equivalent to maximizing feasibility, which in turn is useful for ensuring viability.</p>
<p>Some readers may wonder what the point of defining <math>
<mrow><mi>f</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>x</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> is when it comes to solving linear programs.
The answer is that if one adds a constraint <math>
<mrow><msup><mi>c</mi><mi>T</mi></msup><mspace width="0"/><mi>x</mi><mo lspace="0.278em" rspace="0.278em">≥</mo><msup><mi>k</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup></mrow>
</math> and continually increases <math>
<msup><mi>k</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup>
</math> then the resulting <math>
<msup><mi>ξ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup>
</math> will eventually maximize <math>
<mrow><msup><mi>c</mi><mi>T</mi></msup><mspace width="0"/><msup><mi>ξ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup></mrow>
</math>.
The increasing of <math>
<mi>k</mi>
</math> acts as a "broom" that pushes <math>
<mi>ξ</mi>
</math> towards the optimum along what is known as the <em>central path</em>.
Predictor-corrector methods speed this process up via extrapolation.
But we're of course not seeking to maximize <math>
<mrow><msup><mi>c</mi><mi>T</mi></msup><mspace width="0"/><mi>x</mi></mrow>
</math> but to maximize peace of mind.</p>
<p>A pedagogical point struck me the other day which I will elaborate on.
The definition of <math>
<mrow><mi>f</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>x</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> looks somewhat arbitrary and doesn't lend itself to much intuition at first glance.
But if we rearrange it a bit then we get the following:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>f</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>x</mi><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">=</mo><msub><mo lspace="0" rspace="0.167em" stretchy="false">∑</mo><mi>i</mi></msub><mi>log</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup><mspace width="0"/><mi>x</mi><mo lspace="0.222em" rspace="0.222em">-</mo><msub><mi>b</mi><mi>i</mi></msub><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">=</mo><mi>log</mi><msub><mo lspace="0.167em" rspace="0.167em" stretchy="false">∏</mo><mi>i</mi></msub><msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup><mspace width="0"/><mi>x</mi><mo lspace="0.222em" rspace="0.222em">-</mo><msub><mi>b</mi><mi>i</mi></msub></mrow>
</math>
</span></p>
<p>Maximizing <math>
<mrow><mi>f</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>x</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> is equivalent to maximizing</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>F</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>x</mi><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">=</mo><msup><mi>e</mi><mrow><mi>f</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>x</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0.278em" rspace="0.278em">=</mo><msub><mo lspace="0" rspace="0.167em" stretchy="false">∏</mo><mi>i</mi></msub><msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup><mspace width="0"/><mi>x</mi><mo lspace="0.222em" rspace="0.222em">-</mo><msub><mi>b</mi><mi>i</mi></msub></mrow>
</math>
</span></p>
<p>In other words what we're doing is multiplying together the distances from the current solution to all constraints and looking for the solution that maximizes that product!
This means that <math>
<mrow><mi>F</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>x</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> is in units of the products of the units of all constraints.
If we have two constraints in terms of volume (m³) and five constraints in terms of mass (kg) then <math>
<mrow><mi>F</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>x</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> has units of m⁶kg⁵.</p>
<p>In a system with <math>
<mi>m</mi>
</math> constraints doubling the distance to one constraint only requires reducing the distance to the others by roughly a factor <math>
<mrow><mroot><mn>2</mn><mrow><mi>m</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow></mroot><mo lspace="0.278em" rspace="0.278em">≈</mo><mn>1</mn><mo lspace="0.222em" rspace="0.222em">+</mo><mn>0</mn><mo lspace="0" rspace="0">.</mo><mn>69</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mi>m</mi></mrow>
</math>.
This is the source of the "attenuation" I spoke of earlier.
With a million workplaces, each workplace has to shoulder less than one millionth of the burden of a change to any other workplace.</p>
<p>What we have is effectively a <a href="https://en.wikipedia.org/wiki/Curse_of_dimensionality">blessing of dimensionality</a>.
The extreme points of the system get factorially further and further away from the central ellipsoid the higher the number of dimensions.
When an extreme solution is sought, as is typically the case in linear programming, this fact is a huge problem and part of why solving LP is so difficult.
If one instead seeks centrality this fact becomes a benefit.
It no longer becomes possible that multiple disasters occurring at the same time should threaten the viability of the system,
precisely because the extreme points are very far away from the center.</p>
<p>Finally all this does not exclude that it might be necessary to push for very "stiff" plans in certain locations, especially locations where rapid industrialization is deemed necessary.
In other locations, for example here in Sweden, a more lax approach as I describe above may be called for.
Both approaches can be accommodated within this formalism.</p>
<h3>Another barrier?</h3>
<p>I suspect that it is possible to pick another barrier function such that Newton convergence can be guaranteed for more aggresive updates.
If this can be done then the required solver time drops from months to hours.
One barrier function I have in mind looks like this:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>f</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>x</mi><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">=</mo><msub><mo lspace="0" rspace="0.167em" stretchy="false">∑</mo><mi>i</mi></msub><mi>log</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup><mspace width="0"/><mi>x</mi><mo lspace="0.222em" rspace="0.222em">-</mo><msub><mi>b</mi><mi>i</mi></msub><mo lspace="0" rspace="0.222em" stretchy="false">)</mo><mo lspace="0" rspace="0.222em">-</mo><msub><mi>g</mi><mi>i</mi></msub><mo lspace="0" rspace="0" stretchy="false">[</mo><msub><mi>d</mi><mi>i</mi></msub><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>2</mn><mo lspace="0.222em" rspace="0.222em">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><msubsup><mi>a</mi><mi>i</mi><mi>T</mi></msubsup><mspace width="0"/><mi>x</mi><mo lspace="0.222em" rspace="0.222em">-</mo><msub><mi>b</mi><mi>i</mi></msub><mo lspace="0" rspace="0" stretchy="false">)</mo><msup><mo lspace="0" rspace="0" stretchy="false">]</mo><mn>2</mn></msup></mrow>
</math>
</span></p>
<p>where <math>
<msub><mi>d</mi><mi>i</mi></msub>
</math> is a vector of "diameters" computed by tracing lines from the current solution in the direction towards and away from each constraint.
The square term thus is likely (but not guaranteed) to have its maximum within the feasible region.
What I suspect is that with appropriately chosen large-ish <math>
<msub><mi>g</mi><mi>i</mi></msub>
</math> convergence will be rapid, because without the log term Newton iteration finds the maximum in a single step.
The log term is there only to guarantee that this maximum is within the feasible region.</p>
<p>Whether this barrier function is worthwhile is something I would have to investigate.</p>Marx22 presentation video2022-12-20T15:41:29+01:002022-12-20T15:41:29+01:00tomastag:www.härdin.se,2022-12-20:/blog/2022/12/20/marx22-presentation-video/<video width="960" height="720" poster="http://www.härdin.se/files/videos/marx22.jpg" controls style="max-width:100%;height:auto">
<source src="http://www.härdin.se/files/videos/marx22_720p.mp4" type="video/mp4"/>
<source src="http://www.härdin.se/files/videos/marx22_720p.webm" type="video/webm"/>
Your browser does not support the video tag :(
</video>
<p><a href="http://www.härdin.se/files/videos/CMS2022___presentation.pdf">Click here to download the slides</a>.</p>
<p>The video is also mirrored on <a href="https://www.youtube.com/watch?v=IDuNNqKGMpo">my YouTube channel</a> and on <a href="https://youtu.be/65LjjIQdNw8">Paul Cockshott's channel</a>.</p>
<h2>Video download links</h2>
<p>Because HTML5 doesn't support specifying multiple resolutions in the <video> tag (only <picture> allows that) I have provided download …</p><video width="960" height="720" poster="http://www.härdin.se/files/videos/marx22.jpg" controls style="max-width:100%;height:auto">
<source src="http://www.härdin.se/files/videos/marx22_720p.mp4" type="video/mp4"/>
<source src="http://www.härdin.se/files/videos/marx22_720p.webm" type="video/webm"/>
Your browser does not support the video tag :(
</video>
<p><a href="http://www.härdin.se/files/videos/CMS2022___presentation.pdf">Click here to download the slides</a>.</p>
<p>The video is also mirrored on <a href="https://www.youtube.com/watch?v=IDuNNqKGMpo">my YouTube channel</a> and on <a href="https://youtu.be/65LjjIQdNw8">Paul Cockshott's channel</a>.</p>
<h2>Video download links</h2>
<p>Because HTML5 doesn't support specifying multiple resolutions in the <video> tag (only <picture> allows that) I have provided download links to alternative encodes below:</p>
<p>MP4: <a href="http://www.härdin.se/files/videos/marx22_1134p.mp4">1134p</a> (70M), <a href="http://www.härdin.se/files/videos/marx22_720p.mp4">720p</a> (62M), <a href="http://www.härdin.se/files/videos/marx22_540p.mp4">540p</a> (59M), <a href="http://www.härdin.se/files/videos/marx22_360p.mp4">360p</a> (57M)<br/>
WebM: <a href="http://www.härdin.se/files/videos/marx22_1134p.webm">1134p</a> (68M), <a href="http://www.härdin.se/files/videos/marx22_720p.webm">720p</a> (53M), <a href="http://www.härdin.se/files/videos/marx22_540p.webm">540p</a> (47M), <a href="http://www.härdin.se/files/videos/marx22_360p.webm">360p</a> (43M)</p>Raspberry Pi thermostat2022-12-20T12:04:27+01:002022-12-20T12:04:27+01:00tomastag:www.härdin.se,2022-12-20:/blog/2022/12/20/raspberry-pi-thermostat/<p>Due to various compounding personal reasons I was not able to winterize my house in time this year.
Usually I do this some time in November, before much snow has fallen so it is still accessible by car.
It is a process that involves draining the water system and setting …</p><p>Due to various compounding personal reasons I was not able to winterize my house in time this year.
Usually I do this some time in November, before much snow has fallen so it is still accessible by car.
It is a process that involves draining the water system and setting a thermostat to keep the basement from freezing.
I got delayed until December 16th which means over half a meter of snow had already fallen.
This meant I had to resort to skis to access my house and do the winterization.
Luckily temperatures in the basement hadn't fallen below 2°C despite the delay.</p>
<p><a href="http://www.härdin.se/images/thermostat/strip-IMG_20221216_132141.jpg"><img alt="Ski tracks up to my house" src="http://www.härdin.se/images/thermostat/tstrip-IMG_20221216_132141.jpg"></a></p>
<p>The distance from my house to my neighbor is 300 meters and takes around 20 minutes by skis, 45 minutes with snow shoes.
Not the greatest thing to be forced to do.
I therefore took the opportunity to install a thermostat that can be controlled remotely.
Since I know quite a bit of electronics and how to do computer stuff this felt like a perfect less-than-a-week project.
The result is shown in the two pictures below:</p>
<p><a href="http://www.härdin.se/images/thermostat/strip-IMG_20221216_140923.jpg"><img alt="Box with wall sockets, raspberry pi and relay board" src="http://www.härdin.se/images/thermostat/tstrip-IMG_20221216_140923.jpg"></a></p>
<p><a href="http://www.härdin.se/images/thermostat/strip-IMG_20221216_140957.jpg"><img alt="Box, heater and power strip" src="http://www.härdin.se/images/thermostat/tstrip-IMG_20221216_140957.jpg"></a></p>
<p>A heater is connected to a box which has a wall socket on it and a Raspberry Pi and some relays inside.
A schematic is shown below:</p>
<p><a href="http://www.härdin.se/images/thermostat/thermostat.png"><img alt="Schematic" src="http://www.härdin.se/images/thermostat/thermostat.png"></a></p>
<p>Both relays use 24 V coils and are capable of switching 16 A 230 VAC.
24 V is given by a wall wart.
I use both a 1N4148 and a 1N4007 as freewheeling diodes to get both quick switching and higher current handling capability. It is likely overkill but doesn't hurt.</p>
<p>The circuit board that the relays are soldered to has had copper drilled away in relevant places to improve isolation. In addition the 100 kΩ resistors in series with each MOSFET gate provide extra protection.
Only one relay is used at the moment.</p>
<p>I have two 1-Wire DS18B20 temperature sensors connected.
One sensor is connected via a 3.5 mm mono (TS) phone jack and the other is connected directly via a 3-wire ribbon cable.
I had initially wanted to use parasitically powered sensors but there is currently some kind of bug with the Pi's 1-Wire driver that makes this unreliable. More on that later.</p>
<p>The Pi is connected to the WiFi in my house and can be logged into over SSH by jumping via two other machines.
I hope to reduce this to just one intermediate machine in the future.</p>
<h2>Control, minimizing electricity cost</h2>
<p>One thing that a computerized and internet connected thermostat enables is better temperature control.
Especially with how high electricity prices are at the moment, I want to run the heater when the electricity is the cheapest.
Such information is provided by <a href="https://www.nordpoolgroup.com/">Nord Pool</a>, via a public API for dayahead electricity prices.</p>
<p>Given a thermal model of the basement, optimal heater control can be realized given dayahead prices and the weather forecast.
Doing so involves solving a linear program on the form "minimize cost subject to basement temperature ≥ 4°C".
This program can then be re-formulated and re-solved every hour, yielding desired heater power.
It is tempting to think one should just run the highest power heater at full blast when the electricity is cheapest, but higher basement temperature also means higher thermal leakage.
There is likely an optimal solution between this extreme and just setting a constant thermostat set point.</p>
<p>Currently I have the heater configured to run a bit warmer between 22:00-06:00 on the assumption that electricity is reasonably cheap during these off-hours.
The current setting is +9°C during these hours vs +5°C the rest of the day, with +-1°C hysteresis.</p>
<p>Besides the above, one problem with my current setup is the limited thermal inertia available.
I only have the air as a thermal mass besides the basement itself, and the basement's concrete walls conduct heat away relatively quickly.
I'd prefer something like a sand "battery" that is heated up at optimal times.
Another possibility is to run the water heater since it's already available and water is a good thermal mass.
Whichever mass is used, they provide a "buffer" between heater power applied, the basement's air + water pipes and the walls of the basement.
They therefore allow moving closer to the "max power at the cheapest hour" mode of heating.</p>
<p>Based on statistics over the years I know that roughly 10 kWh/day is necessary to keep the basement above 4°C.
I may write a post in the future diving further into this once I have more statistics.</p>
<h2>Code</h2>
<p>The following Python program is used to control the relay.
It is executed by the pi user on startup by adding the following with <code>crontab -e</code>:</p>
<div class="highlight"><pre><span></span><code><span class="nv">@reboot</span><span class="w"> </span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">python</span><span class="w"> </span><span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="nf">pi</span><span class="o">/</span><span class="n">thermostat</span><span class="p">.</span><span class="n">py</span>
</code></pre></div>
<p>And the code itself:</p>
<div class="highlight"><pre><span></span><code><span class="ch">#!/usr/bin/env python</span>
<span class="kn">from</span> <span class="nn">gpiozero</span> <span class="kn">import</span> <span class="n">LED</span>
<span class="kn">from</span> <span class="nn">time</span> <span class="kn">import</span> <span class="n">sleep</span><span class="p">,</span> <span class="n">time</span><span class="p">,</span> <span class="n">localtime</span>
<span class="kn">from</span> <span class="nn">os.path</span> <span class="kn">import</span> <span class="n">exists</span>
<span class="n">relay_lower</span> <span class="o">=</span> <span class="n">LED</span><span class="p">(</span><span class="mi">23</span><span class="p">)</span>
<span class="n">relay_upper</span> <span class="o">=</span> <span class="n">LED</span><span class="p">(</span><span class="mi">24</span><span class="p">)</span>
<span class="n">relay</span> <span class="o">=</span> <span class="n">relay_upper</span>
<span class="n">relay</span><span class="o">.</span><span class="n">off</span><span class="p">()</span>
<span class="n">on</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">csv</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'/home/pi/thermostat_log.csv'</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">get_temp</span><span class="p">():</span>
<span class="n">filenames</span> <span class="o">=</span> <span class="p">[</span>
<span class="s1">'/sys/bus/w1/devices/28-000008d67211/w1_slave'</span><span class="p">,</span> <span class="c1"># trs</span>
<span class="s1">'/sys/bus/w1/devices/28-000008d6526e/w1_slave'</span><span class="p">,</span> <span class="c1"># backup</span>
<span class="p">]</span>
<span class="k">for</span> <span class="n">filename</span> <span class="ow">in</span> <span class="n">filenames</span><span class="p">:</span>
<span class="k">if</span> <span class="n">exists</span><span class="p">(</span><span class="n">filename</span><span class="p">):</span>
<span class="c1"># read temperature</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="s1">'r'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">t</span> <span class="o">=</span> <span class="nb">float</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">readlines</span><span class="p">()[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">' '</span><span class="p">)[</span><span class="mi">9</span><span class="p">]</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'='</span><span class="p">)[</span><span class="mi">1</span><span class="p">])</span><span class="o">/</span><span class="mi">1000</span>
<span class="k">return</span> <span class="n">t</span>
<span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="s1">'No DS18B20'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">set_relay</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="n">t</span><span class="p">):</span>
<span class="k">global</span> <span class="n">on</span>
<span class="k">global</span> <span class="n">csv</span>
<span class="k">if</span> <span class="n">on</span> <span class="o">!=</span> <span class="n">state</span><span class="p">:</span>
<span class="n">on</span> <span class="o">=</span> <span class="n">state</span>
<span class="k">if</span> <span class="n">state</span><span class="p">:</span>
<span class="n">relay</span><span class="o">.</span><span class="n">on</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">relay</span><span class="o">.</span><span class="n">off</span><span class="p">()</span>
<span class="n">csv</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="si">%f</span><span class="s1">,</span><span class="si">%.3f</span><span class="s1">,</span><span class="si">%i</span><span class="se">\n</span><span class="s1">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">time</span><span class="p">(),</span> <span class="n">t</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">state</span><span class="p">)))</span>
<span class="n">csv</span><span class="o">.</span><span class="n">flush</span><span class="p">()</span>
<span class="c1"># returns (t_on, t_off)</span>
<span class="k">def</span> <span class="nf">limits_per_hour</span><span class="p">(</span><span class="n">hour</span><span class="p">):</span>
<span class="n">cheap_hours</span> <span class="o">=</span> <span class="p">[</span><span class="mi">22</span><span class="p">,</span><span class="mi">23</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span>
<span class="k">if</span> <span class="n">hour</span> <span class="ow">in</span> <span class="n">cheap_hours</span><span class="p">:</span>
<span class="k">return</span> <span class="p">(</span><span class="mi">8</span><span class="p">,</span> <span class="mi">10</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">6</span><span class="p">)</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">get_temp</span><span class="p">()</span>
<span class="n">set_relay</span><span class="p">(</span><span class="kc">False</span><span class="p">,</span> <span class="n">t</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">get_temp</span><span class="p">()</span>
<span class="n">t_on</span><span class="p">,</span> <span class="n">t_off</span> <span class="o">=</span> <span class="n">limits_per_hour</span><span class="p">(</span><span class="n">localtime</span><span class="p">()</span><span class="o">.</span><span class="n">tm_hour</span><span class="p">)</span>
<span class="c1">#print(t_on, t_off, t)</span>
<span class="k">if</span> <span class="n">t</span> <span class="o">>=</span> <span class="mi">85</span><span class="p">:</span>
<span class="c1"># sensor is broken</span>
<span class="k">continue</span>
<span class="k">elif</span> <span class="p">(</span><span class="n">t_on</span> <span class="o"><</span> <span class="n">t_off</span> <span class="ow">and</span> <span class="n">t</span> <span class="o">></span> <span class="n">t_off</span><span class="p">)</span> <span class="ow">or</span> <span class="p">(</span><span class="n">t_on</span> <span class="o">>=</span> <span class="n">t_off</span> <span class="ow">and</span> <span class="n">t</span> <span class="o"><</span> <span class="n">t_off</span><span class="p">):</span>
<span class="n">set_relay</span><span class="p">(</span><span class="kc">False</span><span class="p">,</span> <span class="n">t</span><span class="p">)</span>
<span class="k">elif</span> <span class="p">(</span><span class="n">t_on</span> <span class="o"><</span> <span class="n">t_off</span> <span class="ow">and</span> <span class="n">t</span> <span class="o"><</span> <span class="n">t_on</span> <span class="p">)</span> <span class="ow">or</span> <span class="p">(</span><span class="n">t_on</span> <span class="o">>=</span> <span class="n">t_off</span> <span class="ow">and</span> <span class="n">t</span> <span class="o">></span> <span class="n">t_on</span><span class="p">):</span>
<span class="n">set_relay</span><span class="p">(</span><span class="kc">True</span><span class="p">,</span> <span class="n">t</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'Exception: '</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">))</span>
<span class="n">set_relay</span><span class="p">(</span><span class="kc">False</span><span class="p">,</span> <span class="n">t</span><span class="p">)</span>
<span class="n">sleep</span><span class="p">(</span><span class="mi">60</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="n">set_relay</span><span class="p">(</span><span class="kc">False</span><span class="p">,</span> <span class="n">t</span><span class="p">)</span>
<span class="k">raise</span> <span class="n">e</span>
<span class="k">except</span> <span class="ne">KeyboardInterrupt</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="n">set_relay</span><span class="p">(</span><span class="kc">False</span><span class="p">,</span> <span class="n">t</span><span class="p">)</span>
<span class="k">raise</span> <span class="n">e</span>
</code></pre></div>
<p>The above code will need adapting to your own situation, especially the sensor filenames.</p>
<h2>1-Wire over phone connectors</h2>
<p>There is no official specification for 1-Wire connectors, less so for 1-Wire over phone connectors.
There is a semi-official RJ-11 standard <a href="http://www.midondesign.com/Documents/1-WireApplicationGuide103.pdf">documented here</a>.
There is also a proposed phone connector standard <a href="https://samepins.github.io/doc/1wire.html">here</a> but it suffers from not being usable with mono connectors for parasitically powered devices.
The table below describes what I think would be a sensible standard:</p>
<table>
<tr><th></th><th>Mono (TS)<br/><img src="http://www.härdin.se/images/thermostat/ts-opt.svg" style="width:10em"/></th><th>Stereo (TRS)<br/><img src="http://www.härdin.se/images/thermostat/trs-opt.svg" style="width:10em"/></th><th>TRRS<br/><img src="http://www.härdin.se/images/thermostat/trrs-opt.svg" style="width:10em"/></th></tr>
<tr><td>Tip</td><td>DQ</td><td>DQ</td><td>DQ</td></tr>
<tr><td>Ring</td><td></td><td>VCC</td><td>VCC</td></tr>
<tr><td>Ring</td><td></td><td></td><td>Interrupt</td></tr>
<tr><td>Sleeve</td><td>GND</td><td>GND</td><td>GND</td></tr>
</table>
<p>We can see that the above proposal uses a mono plug for parasitically powered 1-wire devices and a stereo plug for cases where VCC is required, and a TRRS connector when interrupt is available.</p>
<p>Currently the Raspberry Pi 1-wire driver does not appear to follow <a href="https://www.analog.com/media/en/technical-documentation/data-sheets/DS18B20.pdf">Maxim's specifications</a> when it comes to parasitically powered devices.
When using devices that draw considerable power such as the DS18B20 during temperature conversion, the DQ line should be tied to VCC during the conversion.
In fact it appears best to connect DQ to VCC whenever no communication is being done.
This is the reason why many users only get a +85°C reading. Web searching "raspberry pi 1-wire t=85000" gives lots of hits relating to this issue.
Somehow I got parasitic power to work by connecting GPIO3 and GPIO4 together.</p>
<h2>Ways to get get parasitically powered 1-Wire to work on the Raspberry Pi</h2>
<p>The DS18B20 datasheet states that the device uses ~1 mA (1.5 mA max) during temperature conversions, which takes between 93.75 to 750 ms depending on resolution.
A minimum of 3.0 V is required.
The device accepts 5 V but the Raspberry Pi's GPIO pins do not.
Finally the DS18B20 is guaranteed to be able to sink at least 4 mA.</p>
<p>Most of these methods have not been tested yet.</p>
<h3>5 V DQ, lower pullup resistance and Zener</h3>
<p>The DQ line can be driven at 5 V which is readily available on the Raspberry Pi's GPIO header.
With a 1.3 kΩ pullup resistor then DQ will drop no lower than 3.05 V during temperature conversion.
5 V / 1.3 kΩ = 3.85 mA which the device is perfectly capable of sinking.
One might be tempted to think the Pi's GPIO pins can deal with 5 V through a resistor since the pins are capable of sinking up to 16 mA (<a href="http://www.mosaic-industries.com/embedded-systems/microcontroller-projects/raspberry-pi/gpio-pin-electrical-specifications">source</a>).
But this does not apply to the protection diodes.
A Zener diode or five 1N4148's in series can be used instead.</p>
<p><img alt="A circuit corresponding the above" src="http://www.härdin.se/images/thermostat/resistor-diodes.png"></p>
<h3>Capacitor buffered VCC</h3>
<p>A diode and a capacitor can be used to feed VCC.
A limitation to this approach is that the capacitor must be allowed to recharge between conversions.
Its voltage must not drop below 3.0 V during conversion.
Assuming the charge on the capacitor is 3.2 V then its capacitance must be at least <math>
<mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0" rspace="0">.</mo><mn>5</mn><mspace width="0.167em"/><mtext>mA</mtext><mo lspace="0.222em" rspace="0.222em">*</mo><mn>0</mn><mo lspace="0" rspace="0">.</mo><mn>75</mn><mspace width="0.167em"/><mtext>s</mtext><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>0</mn><mo lspace="0" rspace="0">.</mo><mn>2</mn><mspace width="0.167em"/><mtext>V</mtext><mo lspace="0.278em" rspace="0.278em">≈</mo><mn>5</mn><mo lspace="0" rspace="0">.</mo><mn>6</mn><mspace width="0.167em"/><mtext>mF</mtext></mrow>
</math>.
The pullup resistor can be as low as <math>
<mrow><mn>3</mn><mo lspace="0" rspace="0">.</mo><mn>3</mn><mspace width="0.167em"/><mtext>V</mtext><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>4</mn><mspace width="0.167em"/><mtext>mA</mtext><mo lspace="0.278em" rspace="0.278em">=</mo><mn>825</mn><mspace width="0.167em"/><mtext>Ω</mtext></mrow>
</math>.
The time necessary to recharge the capacitor is therefore <math>
<mrow><mi>τ</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>825</mn><mspace width="0.167em"/><mtext>Ω</mtext><mo lspace="0.222em" rspace="0.222em">*</mo><mn>5</mn><mo lspace="0" rspace="0">.</mo><mn>6</mn><mspace width="0.167em"/><mtext>mF</mtext><mo lspace="0.222em" rspace="0.222em">*</mo><mi>log</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0.222em" rspace="0.222em">-</mo><mn>2</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>3</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">≈</mo><mn>5</mn><mspace width="0.167em"/><mtext>s</mtext></mrow>
</math>.
If the standard 4.7 kΩ resistor and a more available 10 mF capacitor are used, then the time comes to <math>
<mrow><mn>4700</mn><mo lspace="0.222em" rspace="0.222em">*</mo><mn>0</mn><mo lspace="0" rspace="0">.</mo><mn>01</mn><mo lspace="0.222em" rspace="0.222em">*</mo><mi>log</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>3</mn><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">≈</mo><mn>52</mn><mspace width="0.167em"/><mtext>s</mtext></mrow>
</math>.
The <math>
<mrow><mi>log</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>3</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> is due to 3.2 V being three times "closer" to 3.3 V than 3.0 V is.</p>
<p>I have not taken the voltage drop across the diode into account here.
As the capacitor gets close to fully charge the current across the diode drops and therefore also its forward voltage drop.
The diode drop is logarithmic in the current, <math>
<mrow><msub><mi>V</mi><mi>d</mi></msub><mo lspace="0.278em" rspace="0.278em">∝</mo><mi>log</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msub><mi>I</mi><mi>d</mi></msub><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math>, so charging the capacitor to 3.2 V likely takes longer than calculated here. Experimentation is required.
A Schottky diode would likely be more appropriate than a 1N4148.</p>
<p><img alt="A circuit corresponding the above" src="http://www.härdin.se/images/thermostat/diode-capacitor.png"></p>
<h3>Connect GPIO3 to GPIO4</h3>
<p>This is what I did. I'm not sure why it works, but it does.
Possibly because pullup is enabled on GPIO3 which supplies just enough extra current for everything to work.</p>
<p><img alt="A circuit corresponding the above" src="http://www.härdin.se/images/thermostat/gpio3.png"></p>
<p>I am not sure how reliable this is, so for now I am using the sensor connected with three wires.
I did not have any TRS jacks on hand, only TS, hence a direct cable connection rather than some nice connectors.</p>
<h3>Lower pullup resistance</h3>
<p>As shown above, as little as 825 Ω should still work.
During conversion DQ may drop as low as 2.06 V.
While this is lower than the minimal voltage specified, the charge stored inside the sensor may be enough to make up the difference, especially when using lower resolution.
The datasheet unfortunately does not specify the value of C<sub>pp</sub>.</p>
<h3>Fixing the driver</h3>
<p>The w1 driver appears to be a binary blob, so I'm not sure if it can be patched.
But if it can, then I would suggest that the GPIO pin output logic high when not communicating with any device.
The GPIO pins are able to supply more than sufficient current for the job.</p>Shadow plans and ghost shifts2022-11-21T13:33:26+02:002022-11-21T13:33:26+02:00tomastag:www.härdin.se,2022-11-21:/blog/2022/11/21/shadow-plans-and-ghost-shifts/<p>Lately I've been thinking of ways to perform "dress rehearsals" for a future democratic planned economy. As I have said on here before, it is important that planning penetrates down to the shop floor and into all communities, that all workers are able to directly engage in formulating the one …</p><p>Lately I've been thinking of ways to perform "dress rehearsals" for a future democratic planned economy. As I have said on here before, it is important that planning penetrates down to the shop floor and into all communities, that all workers are able to directly engage in formulating the one continuously changing plan.</p>
<p>I am convinced that it is important to build institutional knowledge/know-how around planning even before any kind of revolutionary scenario takes place.
To this end I propose two mechanisms: shadow plans and ghost shifts.</p>
<h2>Ghost shifts</h2>
<p>Ghost shifts or rogue operations are one way to seize partial control over the means of production without employers noticing.
A strike produces no value, whereas engaging in rogue production for the commune produces value/use-values "in the opposite direction".
From the workers' point of view we therefore have three scenarios:</p>
<ul>
<li>Business as usual. Workers are exploited. I call this state of affairs minus (-)</li>
<li>Striking. No value is produced, but exploitation may reduce slightly afterwards as a result. Because such gains are eventually undone via mechanisms like inflation, I call this the neutral or zero result (0)</li>
<li>Covertly working for the benefit of the commune. Here value is withheld from the employers and funneled to the commune instead. Therefore I call this a plus (+)</li>
</ul>
<h3>Rate of communalization and rate of cheating</h3>
<p>If we take an average 40 hour work week and a 100% rate of exploitation<sup><a href="#foot1">[1]</a></sup> then 20 hours per week are spent generating one's wage (v, four hours per day) and the remaining 20 hours generating profit (s, also four hours), like so:</p>
<p style="text-align:center"><code>[vvvvssss vvvvssss vvvvssss vvvvssss vvvvssss]</code></p>
<p>Each letter represents one hour.
I use the same symbols as in the English translation of <em>Capital</em>,
so <em>v</em> stands for variable capital and <em>s</em> stands for surplus value.
The surplus value is the amount of time spent per week performing unpaid labour for your employer.
Or put another way, how much you <em>pay your employer for the privilege of working for them!</em></p>
<p>Using the symbol <math>
<mi>κ</mi>
</math> for the time spent working for the benefit of the commune,
I extend the definition of the rate of exploitation to <math>
<mrow><msup><mi>s</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.278em" rspace="0.278em">=</mo><mi>s</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>v</mi><mo lspace="0.222em" rspace="0.222em">+</mo><mi>κ</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math>.
If just one hour per week can be shifted over to communal production then the rate of exploitation falls to <math>
<mrow><msup><mi>s</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.278em" rspace="0.278em">=</mo><mn>19</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>21</mn><mo lspace="0.278em" rspace="0.278em">≈</mo><mn>90</mn><mo lspace="0" rspace="0">%</mo></mrow>
</math>:</p>
<p style="text-align:center"><code>[vvvvssss vvvvssss vvvv<b>κ</b>sss vvvvssss vvvvssss]</code></p>
<p>Notice how a mere 2.5% shift in the work week results in a 10% reduction in the rate of exploitation.</p>
<p>I see two ways of looking closer at this value transference.
The first I will call the <em>rate of communalization</em> (kommunaliseringskvot) denoted <math>
<msup><mi>κ</mi><mo lspace="0" rspace="0">′</mo></msup>
</math>,
which is the fraction of the working week spent working for the benefit of the commune:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msup><mi>κ</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.278em" rspace="0.278em">=</mo><mfrac><mi>κ</mi><mrow><mi>v</mi><mo lspace="0" rspace="0">+</mo><mi>κ</mi><mo lspace="0" rspace="0">+</mo><mi>s</mi></mrow></mfrac></mrow>
</math>
</span></p>
<p>where <math>
<msup><mi>κ</mi><mo lspace="0" rspace="0">′</mo></msup>
</math> ranges from 0% to 100%.
In the example above <math>
<mrow><msup><mi>κ</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>40</mn><mo lspace="0.278em" rspace="0.278em">=</mo><mn>2</mn><mo lspace="0" rspace="0">.</mo><mn>5</mn><mo lspace="0" rspace="0">%</mo></mrow>
</math>.</p>
<p>The second way I will call the <em>rate of cheating</em> (avlurningskvot) denoted <math>
<msup><mi>χ</mi><mo lspace="0" rspace="0">′</mo></msup>
</math>,
which is the fraction of the working week spent "cheating" the employers out of their profits:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msup><mi>χ</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.278em" rspace="0.278em">=</mo><mfrac><mi>κ</mi><mrow><mi>v</mi><mo lspace="0" rspace="0">+</mo><mi>s</mi></mrow></mfrac></mrow>
</math>
</span></p>
<p>where <math>
<msup><mi>χ</mi><mo lspace="0" rspace="0">′</mo></msup>
</math> ranges from zero to infinity.
­<math>
<mrow><msup><mi>χ</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.278em" rspace="0.278em">≥</mo><msup><mi>κ</mi><mo lspace="0" rspace="0">′</mo></msup></mrow>
</math>.
In the example above <math>
<mrow><msup><mi>χ</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>39</mn><mo lspace="0.278em" rspace="0.278em">≈</mo><mn>2</mn><mo lspace="0" rspace="0">.</mo><mn>6</mn><mo lspace="0" rspace="0">%</mo></mrow>
</math>.</p>
<p>If it's one hour <em>every workday</em> then the numbers become <math>
<mrow><msup><mi>s</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.278em" rspace="0.278em">=</mo><mn>15</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>25</mn><mo lspace="0.278em" rspace="0.278em">=</mo><mn>60</mn><mo lspace="0" rspace="0">%</mo></mrow>
</math>, <math>
<mrow><msup><mi>κ</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.278em" rspace="0.278em">=</mo><mn>5</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>40</mn><mo lspace="0.278em" rspace="0.278em">=</mo><mn>12</mn><mo lspace="0" rspace="0">.</mo><mn>5</mn><mo lspace="0" rspace="0">%</mo></mrow>
</math> and <math>
<mrow><msup><mi>χ</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.278em" rspace="0.278em">=</mo><mn>5</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>35</mn><mo lspace="0.278em" rspace="0.278em">≈</mo><mn>14</mn><mo lspace="0" rspace="0">.</mo><mn>3</mn><mo lspace="0" rspace="0">%</mo></mrow>
</math>:</p>
<p style="text-align:center"><code>[vvvvκsss vvvvκsss vvvvκsss vvvvκsss vvvvκsss]</code></p>
<p>Notice that the amount of value taken home by each worker has now risen from 20 hours to 25 hours per week.
This means we could in the best of worlds shorten each workday by one hour:</p>
<p style="text-align:center"><code>[vvvκsss vvvκsss vvvκsss vvvκsss vvvκsss]</code></p>
<p>In the above example I presume the politics play out such that the workers accept a lower wage, knowing that they can still withdraw an amount of goods equivalent to what we had in the very first example.
Due to the pay cut the rate of exploitation goes up: <math>
<mrow><msup><mi>s</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.278em" rspace="0.278em">=</mo><mn>15</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>20</mn><mo lspace="0.278em" rspace="0.278em">=</mo><mn>75</mn><mo lspace="0" rspace="0">%</mo></mrow>
</math>. But the rates of communalization and cheating also go up: <math>
<mrow><msup><mi>κ</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.278em" rspace="0.278em">=</mo><mn>5</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>35</mn><mo lspace="0.278em" rspace="0.278em">≈</mo><mn>14</mn><mo lspace="0" rspace="0">.</mo><mn>3</mn><mo lspace="0" rspace="0">%</mo></mrow>
</math> and <math>
<mrow><msup><mi>χ</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.278em" rspace="0.278em">=</mo><mn>5</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>30</mn><mo lspace="0.278em" rspace="0.278em">≈</mo><mn>16</mn><mo lspace="0" rspace="0">.</mo><mn>7</mn><mo lspace="0" rspace="0">%</mo></mrow>
</math>.</p>
<p>Notice that in all three cases the rate of exploitation is lower than what we started with, and the wage share<sup><a href="#foot2">[2]</a></sup> is higher, which is why I call it a plus.
A strike by comparison looks like this:</p>
<p style="text-align:center"><code>[]</code></p>
<p>This assumes the strikers don't go and do other productive labour.
I also assume that the situation isn't a general strike but a limited strike within a trade union, which is the typical situation here in Sweden.</p>
<p>It might not be immediately obvious why this is beneficial to workers, but the benefit is directly tied to the rate of exploitation.
By working for their employer the worker takes home only ½ hour's worth of value per hour worked, before tax,
whereas when working for the commune they receive one hour's worth, minus deductions for the common fund (roughly tax, around 33%, see the section "On notation" below)<sup><a href="#foot3">[3]</a></sup>.
The workers therefore get better "leverage" on their time by working for the commune.
This means a radically shorter work week in the long run, a situation like this:</p>
<p style="text-align:center"><code>[κκκκ κκκκ κκκκ κκκκ κκκκ]</code></p>
<p>A 20 hour work week with a rate of communalization of 100%.</p>
<p>Ghost shifts are nothing new, but the application of them towards building socialism might be.
At present ghost shifts are done to sell more of some commodity under the table.
It is still commodity production, and it only benefits the workers at one particular workplace.
It cannot benefit from economics of scale, nor benefit from co-operation with other workplaces, nor does it benefit society as a whole.</p>
<h2>Shadow plans</h2>
<p>Much like how opposition parties in bourgeois parliaments may formulate "shadow budgets", the commune could formulate "shadow plans".
By this I mean a kind of "eyeing the prey" of useful means of production that the commune does not yet control.
Such tentative plans could be computed and compared to figure out where best to direct amalgamation efforts.
Workplaces that are easy to incorporate, have dissatisfied workers and that produce the most useful goods and services are prime targets.</p>
<p>Concretely this means attempting to reverse engineer how different workplaces operate, to glean technical coefficients from people outside and inside these workplaces.
The thread <a href="https://casperforum.org/community/cyber/towards-adversarial-planning-for-industrial-action/">Towards Adversarial Planning for Industrial Action</a> on <a href="https://casperforum.org/">CASPER Forum</a> goes into some ideas similar to this.
I have drawn the figure below to hopefully help illustrate the concept:</p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/shadow-plans.svg" alt="Figure demonstrating the concept. A smaller polygon labeled 'currently feasible plans' sits inside a larger polygon labeled 'potentially feasible shadow plans'"/></p>
<p>Adding more productive methods means the <a href="https://en.wikipedia.org/wiki/Polytope">polytope</a> that describes the set of feasible plans grows larger.
I have represented this in the figure by the gray polygon being larger and differently shaped than the inner green one.
The actual polytope is not 2-dimensional but more like 1,000,000,000-dimensional so some imagination is necessary regarding its actual shape.</p>
<p>This is a concept I may develop further in the future.
For now even in this early form it felt appropriate for the spooky theme of this post 👻</p>
<h2>On notation</h2>
<p>I have used a more "Marxian" <math>
<msup><mi>κ</mi><mo lspace="0" rspace="0">′</mo></msup>
</math> and <math>
<msup><mi>χ</mi><mo lspace="0" rspace="0">′</mo></msup>
</math> in this text, but we could use the same strategy as in the post I wrote <a href="http://www.härdin.se/blog/2022/09/21/on-marxian-notation/">on notation</a>.
We have the following instantaneous rates of communalization and cheating:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mstyle scriptlevel="0"><mtable displaystyle="true" columnalign="right left" columnspacing="0.2em"><mtr><mtd><msub><mover><mi>κ</mi><mo accent="true">¯</mo></mover><mo>+</mo></msub></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><mfrac><msub><mi>κ</mi><mo>+</mo></msub><mrow><msub><mi>v</mi><mo>+</mo></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>κ</mi><mo>+</mo></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>s</mi><mo>+</mo></msub></mrow></mfrac></mtd></mtr><mtr><mtd><msub><mover><mi>χ</mi><mo accent="true">¯</mo></mover><mo>+</mo></msub></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><mfrac><msub><mi>κ</mi><mo>+</mo></msub><mrow><msub><mi>v</mi><mo>+</mo></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>s</mi><mo>+</mo></msub></mrow></mfrac></mtd></mtr></mtable></mstyle>
</math>
</span></p>
<p>Obviously the more communalization and the less exploitation the better.
The corresponding regulating depreciations look like this:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mstyle scriptlevel="0"><mtable displaystyle="true" columnalign="right left" columnspacing="0.2em"><mtr><mtd><msub><mover><mi>κ</mi><mo accent="true">¯</mo></mover><mo>-</mo></msub></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><mfrac><mrow><msub><mi>v</mi><mo>-</mo></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>κ</mi><mo>-</mo></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>s</mi><mo>-</mo></msub></mrow><msub><mi>κ</mi><mo>-</mo></msub></mfrac></mtd></mtr><mtr><mtd><msub><mover><mi>χ</mi><mo accent="true">¯</mo></mover><mo>-</mo></msub></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><mfrac><mrow><msub><mi>v</mi><mo>-</mo></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>s</mi><mo>-</mo></msub></mrow><msub><mi>κ</mi><mo>-</mo></msub></mfrac></mtd></mtr></mtable></mstyle>
</math>
</span></p>
<p>We can interpret these two as a high rate of depreciation of wage labour and exploitation being beneficial to the commune. Depreciation in the amount of communalized production on the other hand is detrimental.</p>
<p>Note that <math>
<mi>κ</mi>
</math> breaks down into its own constant (fixed + circulating) and variable parts.
We can call these <math>
<mrow><msub><mi>κ</mi><mi>c</mi></msub><mo lspace="0.278em" rspace="0.278em">=</mo><msub><mi>κ</mi><mi>f</mi></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>κ</mi><mo>∘</mo></msub></mrow>
</math> and <math>
<msub><mi>κ</mi><mi>v</mi></msub>
</math> respectively.
Unlike capital the commune does <em>not</em> benefit from depreciating constant "capital" (means of production), what we might call <math>
<msub><mi>κ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>c</mi><mo lspace="0" rspace="0">,</mo><mo lspace="0" rspace="0">-</mo><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math>.
When <math>
<msub><mi>c</mi><mo>-</mo></msub>
</math> increases <math>
<msub><mover><mi>p</mi><mo accent="true">¯</mo></mover><mo>-</mo></msub>
</math> increases.
Capital prefers to get rid of "dead weight", and does not grow weaker from factories and people being bombed, but stronger.
In contrast an increase in <math>
<msub><mi>κ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>c</mi><mo lspace="0" rspace="0">,</mo><mo lspace="0" rspace="0">-</mo><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math> leads to a <em>decrease</em> in <math>
<msub><mover><mi>χ</mi><mo accent="true">¯</mo></mover><mo>-</mo></msub>
</math>.
The commune does not want its stuff destroyed.
The same goes for depreciation in the labour force itself, or <math>
<msub><mi>κ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>v</mi><mo lspace="0" rspace="0">,</mo><mo lspace="0" rspace="0">-</mo><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math>.
The commune does not want its people dead.</p>
<p>For completeness the full expressions for the rates of cheating when <math>
<mi>κ</mi>
</math> is broken down this way looks like this:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mstyle scriptlevel="0"><mtable displaystyle="true" columnalign="right left" columnspacing="0.2em"><mtr><mtd><msub><mover><mi>χ</mi><mo accent="true">¯</mo></mover><mo>+</mo></msub></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><mfrac><mrow><msub><mi>κ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>f</mi><mo lspace="0" rspace="0">,</mo><mo lspace="0" rspace="0">+</mo><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>κ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mo lspace="0" rspace="0">∘</mo><mo lspace="0" rspace="0">,</mo><mo lspace="0" rspace="0">+</mo><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>κ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>v</mi><mo lspace="0" rspace="0">,</mo><mo lspace="0" rspace="0">+</mo><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub></mrow><mrow><msub><mi>v</mi><mo>+</mo></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>s</mi><mo>+</mo></msub></mrow></mfrac></mtd></mtr><mtr><mtd><msub><mover><mi>χ</mi><mo accent="true">¯</mo></mover><mo>-</mo></msub></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><mfrac><mrow><msub><mi>v</mi><mo>-</mo></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>s</mi><mo>-</mo></msub></mrow><mrow><msub><mi>κ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>f</mi><mo lspace="0" rspace="0">,</mo><mo lspace="0" rspace="0">-</mo><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>κ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mo lspace="0" rspace="0">∘</mo><mo lspace="0" rspace="0">,</mo><mo lspace="0" rspace="0">-</mo><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>κ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>v</mi><mo lspace="0" rspace="0">,</mo><mo lspace="0" rspace="0">-</mo><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub></mrow></mfrac></mtd></mtr></mtable></mstyle>
</math>
</span></p>
<p>I am not sure whether it makes sense to speak of surplus value production here (<math>
<msub><mi>κ</mi><mi>s</mi></msub>
</math>), or whether the value demanded to maintain the non-working population (the young, sick and pensioners) should be accounted as a tax on <math>
<msub><mi>κ</mi><mi>v</mi></msub>
</math>.
Going by the OECD average of 65% employment-to-population ratio<sup><a href="#foot5">[5]</a></sup> and the aforementioned 100% rate of exploitation, we have the following result:
In capitalism each worker supports two non-workers: ½ actual dependent and 1½ dependents' worth of capitalist exploitation.
Or in terms of time: 13⅓ hours for the worker, 6⅔ hours for dependents and 20 hours exploitation per 40 hour week.
In socialism each worker only needs to support the ½ dependent,
a number that is hard to reduce without cheaper healthcare, later retirement or <a href="https://en.wikipedia.org/wiki/%C3%84ttestupa"><em>ättestupa</em></a>.</p>
<h2>Footnotes</h2>
<p><span id="foot1">[1] Rate of exploitation being defined as the ratio between surplus labour performed for your employer divided by the time spent generating your wage, or
­<math>
<mrow><msup><mi>s</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.278em" rspace="0.278em">=</mo><mi>s</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><mi>v</mi></mrow>
</math>. It currently sits around 100% on average worldwide<sup><a href="#foot4">[4]</a></sup>.</span></p>
<p><span id="foot2">[2] The wage share is another way to look at the rate of exploitation. It is defined as the ratio between the time spent generating your wage over the length of the working week, or <math>
<mrow><msup><mi>w</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.278em" rspace="0.278em">=</mo><mi>v</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>s</mi><mo lspace="0.222em" rspace="0.222em">+</mo><mi>v</mi><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">=</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0.222em" rspace="0.222em">+</mo><msup><mi>s</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math>. For the 100% figure in <a href="#foot1">[1]</a> we get <math>
<mrow><msup><mi>w</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.278em" rspace="0.278em">=</mo><mn>50</mn><mo lspace="0" rspace="0">%</mo></mrow>
</math>.</span></p>
<p><span id="foot3">[3] K. Marx, <em>Critique of the Gotha Programme</em>, 1875, <a href="https://www.marxists.org/archive/marx/works/1875/gotha/">https://www.marxists.org/archive/marx/works/1875/gotha/</a> (accessed 2022-11-21).</span></p>
<p><span id="foot4">[4] E. D. Farjoun, M. Machover and D. Zachariah, <em>How Labor Powers the Global Economy: A Labor Theory of Capitalism</em>, Springer Cham, 2022, doi:10.1007/978-3-030-93321-0.</span></p>
<p><span id="foot5">[5] <a href="https://en.wikipedia.org/wiki/Employment-to-population_ratio">https://en.wikipedia.org/wiki/Employment-to-population_ratio</a> (accessed 2022-11-21).</span></p>Video version of my Mises critique2022-11-04T17:48:07+01:002022-11-04T17:48:07+01:00tomastag:www.härdin.se,2022-11-04:/blog/2022/11/04/video-version-of-my-mises-critique/<video width="1280" height="720" poster="http://www.härdin.se/files/videos/mises_critique.jpg" controls style="max-width:100%;height:auto">
<source src="http://www.härdin.se/files/videos/mises_critique_720p.mp4" type="video/mp4"/>
<source src="http://www.härdin.se/files/videos/mises_critique_720p.webm" type="video/webm"/>
Your browser does not support the video tag :(
</video>
<p><a href="https://web.archive.org/web/20141216200523/http://library.freecapitalists.org/books/Ludwig%20von%20Mises/Economic%20Calculation%20in%20the%20Socialist%20Commonwealth.pdf">Mises' text</a></p>
<p><a href="http://www.härdin.se/blog/2021/06/29/a-critique-of-economic-calculation-in-the-socialist-commonwealth/">The original blog post</a></p>
<p><a href="http://www.youtube.com/watch?v=0f-MWeJCsRs">YouTube mirror</a>, <a href="http://www.youtube.com/watch?v=xYd2sS8qwBM">mirror on Cockshott's channel</a></p>
<h2>Download links</h2>
<p>Because HTML5 doesn't support specifying multiple resolutions in the <video> tag (only <picture> allows that) I have provided download links to alternative encodes below:</p>
<p>MP4: <a href="http://www.härdin.se/files/videos/mises_critique_1080p.mp4">1080p</a> (57M), <a href="http://www.härdin.se/files/videos/mises_critique_720p.mp4">720p …</a></p><video width="1280" height="720" poster="http://www.härdin.se/files/videos/mises_critique.jpg" controls style="max-width:100%;height:auto">
<source src="http://www.härdin.se/files/videos/mises_critique_720p.mp4" type="video/mp4"/>
<source src="http://www.härdin.se/files/videos/mises_critique_720p.webm" type="video/webm"/>
Your browser does not support the video tag :(
</video>
<p><a href="https://web.archive.org/web/20141216200523/http://library.freecapitalists.org/books/Ludwig%20von%20Mises/Economic%20Calculation%20in%20the%20Socialist%20Commonwealth.pdf">Mises' text</a></p>
<p><a href="http://www.härdin.se/blog/2021/06/29/a-critique-of-economic-calculation-in-the-socialist-commonwealth/">The original blog post</a></p>
<p><a href="http://www.youtube.com/watch?v=0f-MWeJCsRs">YouTube mirror</a>, <a href="http://www.youtube.com/watch?v=xYd2sS8qwBM">mirror on Cockshott's channel</a></p>
<h2>Download links</h2>
<p>Because HTML5 doesn't support specifying multiple resolutions in the <video> tag (only <picture> allows that) I have provided download links to alternative encodes below:</p>
<p>MP4: <a href="http://www.härdin.se/files/videos/mises_critique_1080p.mp4">1080p</a> (57M), <a href="http://www.härdin.se/files/videos/mises_critique_720p.mp4">720p</a> (40M), <a href="http://www.härdin.se/files/videos/mises_critique_540p.mp4">540p</a> (33M), <a href="http://www.härdin.se/files/videos/mises_critique_360p.mp4">360p</a> (28M)<br/>
WebM: <a href="http://www.härdin.se/files/videos/mises_critique_1080p.webm">1080p</a> (70M), <a href="http://www.härdin.se/files/videos/mises_critique_720p.webm">720p</a> (43M), <a href="http://www.härdin.se/files/videos/mises_critique_540p.webm">540p</a> (32M), <a href="http://www.härdin.se/files/videos/mises_critique_360p.webm">360p</a> (23M)</p>I'm going to Marx22 in Stockholm2022-10-27T13:15:47+02:002022-10-27T13:15:47+02:00tomastag:www.härdin.se,2022-10-27:/blog/2022/10/27/i-m-going-to-marx22-in-stockholm/<p>Me and David Zachariah will be holding a presentation and discussion on cybernetic planning and climate change reversal this Sunday at <a href="https://www.cmsmarx.org/marx22/">Marx22 in Stockholm</a> at <a href="https://www.openstreetmap.org/node/1364657004">ABF-huset, Sveavägen 41, Stockholm</a>. Click <a href="https://www.cmsmarx.org/marx22/konferensschema/">here</a> for the conference scedule. We've heard rumors that the talks will be streamed live, but I have not seen …</p><p>Me and David Zachariah will be holding a presentation and discussion on cybernetic planning and climate change reversal this Sunday at <a href="https://www.cmsmarx.org/marx22/">Marx22 in Stockholm</a> at <a href="https://www.openstreetmap.org/node/1364657004">ABF-huset, Sveavägen 41, Stockholm</a>. Click <a href="https://www.cmsmarx.org/marx22/konferensschema/">here</a> for the conference scedule. We've heard rumors that the talks will be streamed live, but I have not seen any links to said streams yet.</p>
<p>Time: Sunday 12:30-13:30 CET</p>
<p>Room: Kata</p>On Marxian notation2022-09-21T15:07:00+02:002022-09-21T15:07:00+02:00tomastag:www.härdin.se,2022-09-21:/blog/2022/09/21/on-marxian-notation/<p>In working on a future post I noticed my annoyance at Marx' use of the prime (<math>
<msup><mrow/><mo lspace="0" rspace="0">′</mo></msup>
</math>) symbol for the "rates" of various things, such as <math>
<mrow><msup><mi>s</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.278em" rspace="0.278em">=</mo><mi>s</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><mi>v</mi></mrow>
</math> for the rate of exploitation.
The mathematician in me doesn't like this since <math>
<msup><mrow/><mo lspace="0" rspace="0">′</mo></msup>
</math> is often used for derivatives.
For example when dealing …</p><p>In working on a future post I noticed my annoyance at Marx' use of the prime (<math>
<msup><mrow/><mo lspace="0" rspace="0">′</mo></msup>
</math>) symbol for the "rates" of various things, such as <math>
<mrow><msup><mi>s</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.278em" rspace="0.278em">=</mo><mi>s</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><mi>v</mi></mrow>
</math> for the rate of exploitation.
The mathematician in me doesn't like this since <math>
<msup><mrow/><mo lspace="0" rspace="0">′</mo></msup>
</math> is often used for derivatives.
For example when dealing with rocket engines one often speaks of an engine's mass flow rate <math>
<mrow><mi>δ</mi><mspace width="0"/><mi>m</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><mi>δ</mi><mspace width="0"/><mi>t</mi><mo lspace="0.278em" rspace="0.278em">=</mo><msup><mi>m</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.278em" rspace="0.278em">=</mo><mover><mi>m</mi><mo accent="true">·</mo></mover></mrow>
</math> in units of kg/s.
But since both <math>
<mi>s</mi>
</math> and <math>
<mi>v</mi>
</math> have the same units (or else we can't add them), Marx' <math>
<msup><mi>s</mi><mo lspace="0" rspace="0">′</mo></msup>
</math> is unitless, typically expressed as a percentage.</p>
<p>I am also annoyed with the word "rate" in the original German text of <em>Capital</em>, used verbatim in the English translation by Moore and Aveling.
Swedish translations tend to use the word "kvot" (en: <em>ratio</em> or <em>quotient</em>) instead.
Marx also frequently switches between "rate" and "grad" (sv: <em>grad</em>, en: <em>degree</em>) causing even more grief.
Clearly something needs to be done.</p>
<p>To get us started, what notation should we use for the derivative of the rate of exploitation?
Perhaps <math>
<mrow><mi>δ</mi><mspace width="0"/><msup><mi>s</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0" rspace="0" stretchy="false">/</mo><mi>δ</mi><mspace width="0"/><mi>t</mi></mrow>
</math>? We can't use <math>
<msup><mi>s</mi><mrow><mo lspace="0" rspace="0">′</mo><mo lspace="0" rspace="0">′</mo></mrow></msup>
</math> or <math>
<msup><mover><mi>s</mi><mo accent="true">·</mo></mover><mo lspace="0" rspace="0">′</mo></msup>
</math> because that would be silly.
One option is to first switch to the bar (<math>
<mover><mrow/><mo accent="true">¯</mo></mover>
</math>) symbol for Marxian ratios: <math>
<mover><mi>s</mi><mo accent="true">¯</mo></mover>
</math>.
This allows us to use <math>
<msup><mover><mi>s</mi><mo accent="true">¯</mo></mover><mo lspace="0" rspace="0">′</mo></msup>
</math> or <math>
<mover><mover><mi>s</mi><mo accent="true">¯</mo></mover><mo accent="true">·</mo></mover>
</math> as shorthands for <math>
<mrow><mi>δ</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>s</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><mi>v</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0" stretchy="false">/</mo><mi>δ</mi><mspace width="0"/><mi>t</mi></mrow>
</math>.
The Newtonian <math>
<mover><mover><mi>s</mi><mo accent="true">¯</mo></mover><mo accent="true">·</mo></mover>
</math> has the benefit of not conflicting with Marx' notation.</p>
<p>­<math>
<mover><mover><mi>s</mi><mo accent="true">¯</mo></mover><mo accent="true">·</mo></mover>
</math> has units of Hz (s<sup>-1</sup>), but didactically it makes more sense to say %/s or %/year depending on scaling.
What of <math>
<mi>c</mi>
</math>, <math>
<mi>v</mi>
</math> and <math>
<mi>s</mi>
</math> themselves?
It has been pointed out to me by David Zachariah that this triad has units of <em>persons</em>.
This makes accumulated value have units of <em>person-seconds</em>:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msup><mi>s</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup><mo lspace="0.278em" rspace="0.278em">=</mo><mo lspace="0" rspace="0.167em" stretchy="false">∫</mo><mi>s</mi><mspace width="0.167em"/><mi>d</mi><mspace width="0"/><mi>t</mi><mspace width="0.333em"/><mtext>[Ps]</mtext></mrow>
</math>
</span></p>
<p>where <math>
<msup><mrow/><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup>
</math> is used to denote an antiderivative.
A physical unit for people would be useful, and I have used <em>P</em> above.
It does have the downside of already being used for <a href="https://en.wikipedia.org/wiki/Poise_(unit)">poise</a>.</p>
<p>If we're already in the business of putting Marx' atrocious notation "back on its feet" then we could ditch Marx' <math>
<mrow><mi>C</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mi>c</mi><mo lspace="0.222em" rspace="0.222em">+</mo><mi>v</mi></mrow>
</math> and use the usual uppercase shorthands for antiderivatives:</p>
<ul>
<li><math>
<mrow><mi>C</mi><mo lspace="0.278em" rspace="0.278em">=</mo><msup><mi>c</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup></mrow>
</math> for historically accumulated and depreciated fixed and circulating capital (dead labour)</li>
<li><math>
<mrow><mi>V</mi><mo lspace="0.278em" rspace="0.278em">=</mo><msup><mi>v</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup></mrow>
</math> for the present working population and its petty personal possessions (living labour)</li>
<li><math>
<mrow><mi>S</mi><mo lspace="0.278em" rspace="0.278em">=</mo><msup><mi>s</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup></mrow>
</math> for historically accumulated and depreciated surplus (pyramids, yachts etc.)</li>
</ul>
<p>All three of these are, of course, capital letters.</p>
<p>I have brought up depreciation here to highlight that <math>
<mi>c</mi>
</math>, <math>
<mi>v</mi>
</math> and <math>
<mi>s</mi>
</math> should themselves be broken down as follows:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mstyle scriptlevel="0"><mtable displaystyle="true" columnalign="right left" columnspacing="0.2em"><mtr><mtd><mi>c</mi></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><msub><mi>c</mi><mo>+</mo></msub><mo lspace="0.222em" rspace="0.222em">-</mo><msub><mi>c</mi><mo>-</mo></msub></mtd></mtr><mtr><mtd><mi>v</mi></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><msub><mi>v</mi><mo>+</mo></msub><mo lspace="0.222em" rspace="0.222em">-</mo><msub><mi>v</mi><mo>-</mo></msub></mtd></mtr><mtr><mtd><mi>s</mi></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><msub><mi>s</mi><mo>+</mo></msub><mo lspace="0.222em" rspace="0.222em">-</mo><msub><mi>s</mi><mo>-</mo></msub></mtd></mtr></mtable></mstyle>
</math>
</span></p>
<p>The positives correspond to production and the negatives to depreciation.
In a steady state economy production precisely equals depreciation.
More fully we have this:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mstyle scriptlevel="0"><mtable displaystyle="true" columnalign="right left" columnspacing="0.2em"><mtr><mtd><mi>C</mi></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><mi>C</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>t</mi><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">=</mo><munderover><mo lspace="0" rspace="0.167em" stretchy="false">∫</mo><mrow><mo lspace="0" rspace="0">-</mo><mi mathvariant="normal">∞</mi></mrow><mi>t</mi></munderover><mi>c</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>τ</mi><mo lspace="0" rspace="0.167em" stretchy="false">)</mo><mi>d</mi><mspace width="0"/><mi>τ</mi><mo lspace="0.278em" rspace="0.278em">=</mo><munderover><mo lspace="0" rspace="0" stretchy="false">∫</mo><mrow><mo lspace="0" rspace="0">-</mo><mi mathvariant="normal">∞</mi></mrow><mi>t</mi></munderover><mo lspace="0" rspace="0" stretchy="false">(</mo><msub><mi>c</mi><mo>+</mo></msub><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>τ</mi><mo lspace="0" rspace="0.222em" stretchy="false">)</mo><mo lspace="0" rspace="0.222em">-</mo><msub><mi>c</mi><mo>-</mo></msub><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>τ</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0.167em" stretchy="false">)</mo><mi>d</mi><mspace width="0"/><mi>τ</mi></mtd></mtr><mtr><mtd><mi>V</mi></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><mi>V</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>t</mi><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">=</mo><munderover><mo lspace="0" rspace="0.167em" stretchy="false">∫</mo><mrow><mo lspace="0" rspace="0">-</mo><mi mathvariant="normal">∞</mi></mrow><mi>t</mi></munderover><mi>v</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>τ</mi><mo lspace="0" rspace="0.167em" stretchy="false">)</mo><mi>d</mi><mspace width="0"/><mi>τ</mi><mo lspace="0.278em" rspace="0.278em">=</mo><munderover><mo lspace="0" rspace="0" stretchy="false">∫</mo><mrow><mo lspace="0" rspace="0">-</mo><mi mathvariant="normal">∞</mi></mrow><mi>t</mi></munderover><mo lspace="0" rspace="0" stretchy="false">(</mo><msub><mi>v</mi><mo>+</mo></msub><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>τ</mi><mo lspace="0" rspace="0.222em" stretchy="false">)</mo><mo lspace="0" rspace="0.222em">-</mo><msub><mi>v</mi><mo>-</mo></msub><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>τ</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0.167em" stretchy="false">)</mo><mi>d</mi><mspace width="0"/><mi>τ</mi></mtd></mtr><mtr><mtd><mi>S</mi></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><mi>S</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>t</mi><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">=</mo><munderover><mo lspace="0" rspace="0.167em" stretchy="false">∫</mo><mrow><mo lspace="0" rspace="0">-</mo><mi mathvariant="normal">∞</mi></mrow><mi>t</mi></munderover><mi>s</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>τ</mi><mo lspace="0" rspace="0.167em" stretchy="false">)</mo><mi>d</mi><mspace width="0"/><mi>τ</mi><mo lspace="0.278em" rspace="0.278em">=</mo><munderover><mo lspace="0" rspace="0" stretchy="false">∫</mo><mrow><mo lspace="0" rspace="0">-</mo><mi mathvariant="normal">∞</mi></mrow><mi>t</mi></munderover><mo lspace="0" rspace="0" stretchy="false">(</mo><msub><mi>s</mi><mo>+</mo></msub><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>τ</mi><mo lspace="0" rspace="0.222em" stretchy="false">)</mo><mo lspace="0" rspace="0.222em">-</mo><msub><mi>s</mi><mo>-</mo></msub><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>τ</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0.167em" stretchy="false">)</mo><mi>d</mi><mspace width="0"/><mi>τ</mi></mtd></mtr></mtable></mstyle>
</math>
</span></p>
<p>Let us see what different sorts of "rates" we can reason about with this more sensible notation.
Rate of exploitation (<em>utsugningskvot</em>) and rate of profit (<em>profitkvot</em>) look just about the same:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mstyle scriptlevel="0"><mtable displaystyle="true" columnalign="right left" columnspacing="0.2em"><mtr><mtd><msup><mi>s</mi><mo lspace="0" rspace="0">′</mo></msup></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><mfrac><mi>S</mi><mi>V</mi></mfrac></mtd></mtr><mtr><mtd><msup><mi>p</mi><mo lspace="0" rspace="0">′</mo></msup></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><mfrac><mi>S</mi><mrow><mi>C</mi><mo lspace="0.222em" rspace="0.222em">+</mo><mi>V</mi></mrow></mfrac></mtd></mtr></mtable></mstyle>
</math>
</span></p>
<p>But we can also look at the situation like this:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mstyle scriptlevel="0"><mtable displaystyle="true" columnalign="right left" columnspacing="0.2em"><mtr><mtd><msub><mover><mi>s</mi><mo accent="true">¯</mo></mover><mo>+</mo></msub></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><mfrac><msub><mi>s</mi><mo>+</mo></msub><msub><mi>v</mi><mo>+</mo></msub></mfrac></mtd></mtr><mtr><mtd><msub><mover><mi>p</mi><mo accent="true">¯</mo></mover><mo>+</mo></msub></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><mfrac><msub><mi>s</mi><mo>+</mo></msub><mrow><msub><mi>c</mi><mo>+</mo></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>v</mi><mo>+</mo></msub></mrow></mfrac></mtd></mtr></mtable></mstyle>
</math>
</span></p>
<p>If we think about this very carefully we will realize that <math>
<msub><mover><mi>p</mi><mo accent="true">¯</mo></mover><mo>+</mo></msub>
</math> here is close to the Shaikhian notion of <em>regulating capital</em> (<math>
<msub><mi>π</mi><mi>t</mi></msub>
</math>), the "instantaneous" rate of profit.
This is <em>not</em> the same as the current historical profit rate <math>
<msup><mi>p</mi><mo lspace="0" rspace="0">′</mo></msup>
</math>, nor will integrating Shaikhian regulating profit rates result in this historical profit rate:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mstyle scriptlevel="0"><mtable displaystyle="true" columnalign="right left" columnspacing="0.2em"><mtr><mtd><msup><mi>p</mi><mo lspace="0" rspace="0">′</mo></msup><mo lspace="0.278em" rspace="0.278em">=</mo><mfrac><mi>S</mi><mrow><mi>C</mi><mo lspace="0.222em" rspace="0.222em">+</mo><mi>V</mi></mrow></mfrac></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><mfrac><mrow><mo lspace="0" rspace="0.167em" stretchy="false">∫</mo><mi>s</mi><mspace width="0.167em"/><mi>d</mi><mspace width="0"/><mi>t</mi></mrow><mrow><mo lspace="0" rspace="0" stretchy="false">∫</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>c</mi><mo lspace="0.222em" rspace="0.222em">+</mo><mi>v</mi><mo lspace="0" rspace="0.167em" stretchy="false">)</mo><mi>d</mi><mspace width="0"/><mi>t</mi></mrow></mfrac></mtd></mtr><mtr><mtd><msub><mover><mi>P</mi><mo accent="true">¯</mo></mover><mo>+</mo></msub><mo lspace="0.278em" rspace="0.278em">=</mo><msubsup><mover><mi>p</mi><mo accent="true">¯</mo></mover><mo>+</mo><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msubsup></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><mo lspace="0" rspace="0.167em" stretchy="false">∫</mo><mfrac><msub><mi>s</mi><mo>+</mo></msub><mrow><msub><mi>c</mi><mo>+</mo></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>v</mi><mo>+</mo></msub></mrow></mfrac><mspace width="0.167em"/><mi>d</mi><mspace width="0"/><mi>t</mi></mtd></mtr><mtr><mtd><mfrac><mrow><mo lspace="0" rspace="0.167em" stretchy="false">∫</mo><mi>s</mi><mspace width="0.167em"/><mi>d</mi><mspace width="0"/><mi>t</mi></mrow><mrow><mo lspace="0" rspace="0" stretchy="false">∫</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>c</mi><mo lspace="0.222em" rspace="0.222em">+</mo><mi>v</mi><mo lspace="0" rspace="0.167em" stretchy="false">)</mo><mi>d</mi><mspace width="0"/><mi>t</mi></mrow></mfrac></mtd><mtd><mo lspace="0" rspace="0.278em">≠</mo><mo lspace="0" rspace="0.167em" stretchy="false">∫</mo><mfrac><msub><mi>s</mi><mo>+</mo></msub><mrow><msub><mi>c</mi><mo>+</mo></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>v</mi><mo>+</mo></msub></mrow></mfrac><mspace width="0.167em"/><mi>d</mi><mspace width="0"/><mi>t</mi></mtd></mtr></mtable></mstyle>
</math>
</span></p>
<p>This quirk is at the heart of an ongoing academic debate between Anwar Shaikh and Victor Magariño on one side and Paul Cockshott on the other.
If however <math>
<msub><mi>c</mi><mo>+</mo></msub>
</math>, <math>
<msub><mi>v</mi><mo>+</mo></msub>
</math> and <math>
<msub><mi>s</mi><mo>+</mo></msub>
</math> are held constant then we expect <math>
<mrow><munder><mo lspace="0" rspace="0.167em" movablelimits="false">lim</mo><mrow><mi>t</mi><mo lspace="0" rspace="0">→</mo><mi mathvariant="normal">∞</mi></mrow></munder><mover><mi>P</mi><mo accent="true">¯</mo></mover><mo lspace="0.278em" rspace="0.278em">=</mo><msup><mi>p</mi><mo lspace="0" rspace="0">′</mo></msup></mrow>
</math> since all capital and surplus eventually depreciates.</p>
<p>I will also introduce the following two definitions:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mstyle scriptlevel="0"><mtable displaystyle="true" columnalign="right left" columnspacing="0.2em"><mtr><mtd><msub><mover><mi>s</mi><mo accent="true">¯</mo></mover><mo>-</mo></msub></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><mfrac><msub><mi>v</mi><mo>-</mo></msub><msub><mi>s</mi><mo>-</mo></msub></mfrac></mtd></mtr><mtr><mtd><msub><mover><mi>p</mi><mo accent="true">¯</mo></mover><mo>-</mo></msub></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><mfrac><mrow><msub><mi>c</mi><mo>-</mo></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>v</mi><mo>-</mo></msub></mrow><msub><mi>s</mi><mo>-</mo></msub></mfrac></mtd></mtr></mtable></mstyle>
</math>
</span></p>
<p>Just as <math>
<msub><mover><mi>p</mi><mo accent="true">¯</mo></mover><mo>+</mo></msub>
</math> regulates the rate of profit, so does <math>
<msub><mover><mi>p</mi><mo accent="true">¯</mo></mover><mo>-</mo></msub>
</math>.
We could therefore call <math>
<msub><mover><mi>p</mi><mo accent="true">¯</mo></mover><mo>-</mo></msub>
</math> the <em>regulating depreciation</em>.
We have three constituent variables to consider here, with their own effects:</p>
<p>­<math>
<msub><mi>c</mi><mo>-</mo></msub>
</math>: the rate of depreciation of constant capital.
The faster constant capital depreciates the higher the rate of profit, since capital does not have to maintain older less productive means of production.
One reason war happens is because bombing factories increases <math>
<msub><mi>c</mi><mo>-</mo></msub>
</math> which in turn increases <math>
<msub><mover><mi>p</mi><mo accent="true">¯</mo></mover><mo>-</mo></msub>
</math> and over time <math>
<msup><mi>p</mi><mo lspace="0" rspace="0">′</mo></msup>
</math>.
This is detrimental to individual capitals, but beneficial to capital as a whole.</p>
<p>­<math>
<msub><mi>v</mi><mo>-</mo></msub>
</math>: the rate of depreciation of variable capital, or the rate of depreciation of labour power.
One obvious way this happens is through death.
It also explains why bourgeois parties are pro privatizing elderly care.
Either you can afford it or you die, which means unproductive workers are disposed of more quickly.
As a bonus, capital profits off of the privatized elderly care itself.
Another way to raise <math>
<msub><mi>v</mi><mo>-</mo></msub>
</math> is to increase the pension age.
This forces workers to be productive for more of their lives, followed by hopefully dying as soon as possible after retirement.
Yet another way to increase <math>
<msub><mi>v</mi><mo>-</mo></msub>
</math> is to simply steal the workers' personal property.
This can happen through legalized gambling, but also happens through regular theft, thievery being a fundamentally petty bourgeois occupation.
Turning workers into slaves is yet another way to raise <math>
<msub><mi>v</mi><mo>-</mo></msub>
</math>,
which happens today in places like Libya.</p>
<p>­<math>
<msub><mi>s</mi><mo>-</mo></msub>
</math>: the rate of depreciation of surplus value.
The bourgeoisie wants <math>
<msub><mi>s</mi><mo>-</mo></msub>
</math> to be kept as low as possible.
They do this by investing their surplus into things that depreciate slowly,
things like gold, silver, fine art, antiques and so on.
The ultimate thing that never depreciates here on Earth is land and bodies of water.
The latter is not yet privatized but bourgeois activists like Nalle Wahlroos, who has been advocating privatizing the Baltic Sea(!) and the atmosphere(!!), are hard at work on the issue.</p>
<p>Notice how war does not alter the rate of exploitation while it increases the rate of profit.
This is one reason why it is in workers' interests to oppose bourgeois wars, beyond them causing death and suffering.
War also involves the transfer of ownership of land.
Because land doesn't depreciate this is another explanation for bourgeois war.</p>
<p>While land itself usually doesn't depreciate, what is on the land can and does depreciate.
Forests for example are bookkept separately from the land they are on, and will depreciate if not looked after properly.
One way land can depreciate is by being lost to rising sea levels.</p>
<p>How about the change in rate of exploitation over time?
Because <math>
<msub><mover><mi>s</mi><mo accent="true">¯</mo></mover><mo>+</mo></msub>
</math> is a ratio we must make use of both the product rule and the chain rule:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mstyle scriptlevel="0"><mtable displaystyle="true" columnalign="right left" columnspacing="0.2em"><mtr><mtd><msub><mover><mover><mi>s</mi><mo accent="true">¯</mo></mover><mo accent="true">·</mo></mover><mo>+</mo></msub></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><mfrac><mi>δ</mi><mrow><mi>δ</mi><mspace width="0"/><mi>t</mi></mrow></mfrac><mfrac><msub><mi>s</mi><mo>+</mo></msub><msub><mi>v</mi><mo>+</mo></msub></mfrac></mtd></mtr><mtr><mtd/><mtd><mo lspace="0" rspace="0.278em">=</mo><mfrac><mn>1</mn><msub><mi>v</mi><mo>+</mo></msub></mfrac><mfrac><mrow><mi>δ</mi><mspace width="0"/><msub><mi>s</mi><mo>+</mo></msub></mrow><mrow><mi>δ</mi><mspace width="0"/><mi>t</mi></mrow></mfrac><mo lspace="0.222em" rspace="0.222em">-</mo><mfrac><msub><mi>s</mi><mo>+</mo></msub><msubsup><mi>v</mi><mo>+</mo><mn>2</mn></msubsup></mfrac><mfrac><mrow><mi>δ</mi><mspace width="0"/><msub><mi>v</mi><mo>+</mo></msub></mrow><mrow><mi>δ</mi><mspace width="0"/><mi>t</mi></mrow></mfrac></mtd></mtr><mtr><mtd/><mtd><mo lspace="0" rspace="0.278em">=</mo><mfrac><msub><mover><mi>s</mi><mo accent="true">·</mo></mover><mo>+</mo></msub><msub><mi>v</mi><mo>+</mo></msub></mfrac><mo lspace="0.222em" rspace="0.222em">-</mo><mfrac><mrow><msub><mi>s</mi><mo>+</mo></msub><mspace width="0"/><msub><mover><mi>v</mi><mo accent="true">·</mo></mover><mo>+</mo></msub></mrow><msubsup><mi>v</mi><mo>+</mo><mn>2</mn></msubsup></mfrac></mtd></mtr></mtable></mstyle>
</math>
</span></p>
<p>The result has units of Hz.
Informally we see the rate of exploitation goes up if profits increase, and down if wages increase.
For the rate of profit the situation is similar:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mstyle scriptlevel="0"><mtable displaystyle="true" columnalign="right left" columnspacing="0.2em"><mtr><mtd><msub><mover><mover><mi>p</mi><mo accent="true">¯</mo></mover><mo accent="true">·</mo></mover><mo>+</mo></msub></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><mfrac><mi>δ</mi><mrow><mi>δ</mi><mspace width="0"/><mi>t</mi></mrow></mfrac><mfrac><msub><mi>s</mi><mo>+</mo></msub><mrow><msub><mi>c</mi><mo>+</mo></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>v</mi><mo>+</mo></msub></mrow></mfrac></mtd></mtr><mtr><mtd/><mtd><mo lspace="0" rspace="0.278em">=</mo><mfrac><mn>1</mn><mrow><msub><mi>c</mi><mo>+</mo></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>v</mi><mo>+</mo></msub></mrow></mfrac><mfrac><mrow><mi>δ</mi><mspace width="0"/><msub><mi>s</mi><mo>+</mo></msub></mrow><mrow><mi>δ</mi><mspace width="0"/><mi>t</mi></mrow></mfrac><mo lspace="0.222em" rspace="0.222em">-</mo><mfrac><msub><mi>s</mi><mo>+</mo></msub><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><msub><mi>c</mi><mo>+</mo></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>v</mi><mo>+</mo></msub><msup><mo lspace="0" rspace="0" stretchy="false">)</mo><mn>2</mn></msup></mrow></mfrac><mspace width="0.167em"/><mrow><mo stretchy="true">(</mo><mrow><mfrac><mrow><mi>δ</mi><mspace width="0"/><msub><mi>c</mi><mo>+</mo></msub></mrow><mrow><mi>δ</mi><mspace width="0"/><mi>t</mi></mrow></mfrac><mo lspace="0.222em" rspace="0.222em">+</mo><mfrac><mrow><mi>δ</mi><mspace width="0"/><msub><mi>v</mi><mo>+</mo></msub></mrow><mrow><mi>δ</mi><mspace width="0"/><mi>t</mi></mrow></mfrac></mrow><mo stretchy="true">)</mo></mrow></mtd></mtr><mtr><mtd/><mtd><mo lspace="0" rspace="0.278em">=</mo><mfrac><msub><mover><mi>s</mi><mo accent="true">·</mo></mover><mo>+</mo></msub><mrow><msub><mi>c</mi><mo>+</mo></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>v</mi><mo>+</mo></msub></mrow></mfrac><mo lspace="0.222em" rspace="0.222em">-</mo><mfrac><mrow><msub><mi>s</mi><mo>+</mo></msub><mo lspace="0" rspace="0" stretchy="false">(</mo><msub><mover><mi>c</mi><mo accent="true">·</mo></mover><mo>+</mo></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mover><mi>v</mi><mo accent="true">·</mo></mover><mo>+</mo></msub><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><msub><mi>c</mi><mo>+</mo></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>v</mi><mo>+</mo></msub><msup><mo lspace="0" rspace="0" stretchy="false">)</mo><mn>2</mn></msup></mrow></mfrac></mtd></mtr></mtable></mstyle>
</math>
</span></p>
<p>The above two formulas describe what we could call the <em>indirect</em> effects of changes in <math>
<mi>c</mi>
</math>, <math>
<mi>v</mi>
</math> and <math>
<mi>s</mi>
</math>.
If we instead differentiate the two rates with respect to the three variables we get the following results:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mstyle scriptlevel="0"><mtable displaystyle="true" columnalign="right left" columnspacing="0.2em"><mtr><mtd><mfrac><mrow><mi>δ</mi><mspace width="0"/><msub><mover><mi>p</mi><mo accent="true">¯</mo></mover><mo>+</mo></msub></mrow><mrow><mi>δ</mi><mspace width="0"/><msub><mi>c</mi><mo>+</mo></msub></mrow></mfrac></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><mo lspace="0" rspace="0">-</mo><mfrac><msub><mi>s</mi><mo>+</mo></msub><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><msub><mi>c</mi><mo>+</mo></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>v</mi><mo>+</mo></msub><msup><mo lspace="0" rspace="0" stretchy="false">)</mo><mn>2</mn></msup></mrow></mfrac></mtd></mtr><mtr><mtd><mfrac><mrow><mi>δ</mi><mspace width="0"/><msub><mover><mi>p</mi><mo accent="true">¯</mo></mover><mo>+</mo></msub></mrow><mrow><mi>δ</mi><mspace width="0"/><msub><mi>v</mi><mo>+</mo></msub></mrow></mfrac></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><mo lspace="0" rspace="0">-</mo><mfrac><msub><mi>s</mi><mo>+</mo></msub><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><msub><mi>c</mi><mo>+</mo></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>v</mi><mo>+</mo></msub><msup><mo lspace="0" rspace="0" stretchy="false">)</mo><mn>2</mn></msup></mrow></mfrac></mtd></mtr><mtr><mtd><mfrac><mrow><mi>δ</mi><mspace width="0"/><msub><mover><mi>p</mi><mo accent="true">¯</mo></mover><mo>+</mo></msub></mrow><mrow><mi>δ</mi><mspace width="0"/><msub><mi>s</mi><mo>+</mo></msub></mrow></mfrac></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><mfrac><mn>1</mn><mrow><msub><mi>c</mi><mo>+</mo></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>v</mi><mo>+</mo></msub></mrow></mfrac></mtd></mtr></mtable></mstyle>
</math>
</span></p>
<p>Note the similarity with <math>
<msub><mover><mover><mi>p</mi><mo accent="true">¯</mo></mover><mo accent="true">·</mo></mover><mo>+</mo></msub>
</math>.
The first two relations tell us that increases in the amount of value that has to be ploughed into inputs (<math>
<msub><mi>c</mi><mo>+</mo></msub>
</math>) or wages (<math>
<msub><mi>v</mi><mo>+</mo></msub>
</math>) affect the rate of profit negatively and in the same way.
It makes no difference to the capitalist whether he (or she!) has to spend money on more coal or on hiring more people.
The third tells us that an increase in the rate at which surplus is extracted raises the regulating profit rate.</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mstyle scriptlevel="0"><mtable displaystyle="true" columnalign="right left" columnspacing="0.2em"><mtr><mtd><mfrac><mrow><mi>δ</mi><mspace width="0"/><msub><mover><mi>s</mi><mo accent="true">¯</mo></mover><mo>+</mo></msub></mrow><mrow><mi>δ</mi><mspace width="0"/><msub><mi>c</mi><mo>+</mo></msub></mrow></mfrac></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><mn>0</mn></mtd></mtr><mtr><mtd><mfrac><mrow><mi>δ</mi><mspace width="0"/><msub><mover><mi>s</mi><mo accent="true">¯</mo></mover><mo>+</mo></msub></mrow><mrow><mi>δ</mi><mspace width="0"/><msub><mi>v</mi><mo>+</mo></msub></mrow></mfrac></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><mo lspace="0" rspace="0">-</mo><mfrac><msub><mi>s</mi><mo>+</mo></msub><msubsup><mi>v</mi><mo>+</mo><mn>2</mn></msubsup></mfrac></mtd></mtr><mtr><mtd><mfrac><mrow><mi>δ</mi><mspace width="0"/><msub><mover><mi>s</mi><mo accent="true">¯</mo></mover><mo>+</mo></msub></mrow><mrow><mi>δ</mi><mspace width="0"/><msub><mi>s</mi><mo>+</mo></msub></mrow></mfrac></mtd><mtd><mo lspace="0" rspace="0.278em">=</mo><mfrac><mn>1</mn><msub><mi>v</mi><mo>+</mo></msub></mfrac></mtd></mtr></mtable></mstyle>
</math>
</span></p>
<p>Here the similarity is with <math>
<msub><mover><mover><mi>s</mi><mo accent="true">¯</mo></mover><mo accent="true">·</mo></mover><mo>+</mo></msub>
</math>.
We see first that it makes no difference to the workers how much dead labour is embodied in the inputs.
They arrive "for free", their value simply being passed onto the output.
What the workers do care about are the second and third relations.
Higher pay -> less exploitation, more unpaid work -> more exploitation.</p>
<p>This same analysis could be carried out for <math>
<msub><mover><mi>s</mi><mo accent="true">¯</mo></mover><mo>-</mo></msub>
</math> and <math>
<msub><mover><mi>p</mi><mo accent="true">¯</mo></mover><mo>-</mo></msub>
</math> but this post is already long enough so I leave that as an exercise for you dear reader.</p>Ubuntu 22.04 support added to FmiGo!2022-07-04T08:16:25+02:002022-07-04T08:16:25+02:00tomastag:www.härdin.se,2022-07-04:/blog/2022/07/04/ubuntu-22-04-support-added-to-fmigo/<p>Three days ago I pushed support for <a href="https://www.releases.ubuntu.com/22.04/">Ubuntu 22.04 LTS (Jammy Jellyfish)</a> to <a href="//www.fmigo.net">FmiGo</a>.
This has been sitting on my disk for a month or two and I finally got around to testing, cleaning it up and pushing it.
This post is mostly a shameless ploy to get more …</p><p>Three days ago I pushed support for <a href="https://www.releases.ubuntu.com/22.04/">Ubuntu 22.04 LTS (Jammy Jellyfish)</a> to <a href="//www.fmigo.net">FmiGo</a>.
This has been sitting on my disk for a month or two and I finally got around to testing, cleaning it up and pushing it.
This post is mostly a shameless ploy to get more inlinks to the site, hopefully boosting it in search results.
There are dozens of people reading this. Dozens!</p>
<p>More seriously the work I did on FmiGo was useful for getting an understanding how coupled systems behave.
In particular how difficult it is to ensure that two simulators coupled together are numerically stable and don't explode.
This has some relevance to the work I'm currently doing on economic planning.
It suggests that a loosely coupled economy will tend to be unstable.
We see this in the real world with capitalism's tendency to crash every 7 years or so.
It is also relevant when it comes to proposals for "decentralized" planning.
If the solver itself is decentralized then you will encounter the kind of numerical instabilities we dealt with in the FmiGo project.
Note that this doesn't mean that the decisions about what should go into the planning system can't be decentralized.
Only that a single set of equations solved in a single solver will be easier to deal with.
This amounts to model exchange.</p>Homepage updated, FmiGo mentioned2022-06-22T00:16:27+02:002022-06-22T00:16:27+02:00tomastag:www.härdin.se,2022-06-22:/blog/2022/06/22/homepage-updated-fmigo-mentioned/<p>I noticed just now that I don't have a link to the <a href="//www.fmigo.net/">FmiGo</a> website on this site,
so I took the opportunity to update the landing page with a mention of the project.
Me and Claude would like to see it picked up by someone, or perhaps a continuation of …</p><p>I noticed just now that I don't have a link to the <a href="//www.fmigo.net/">FmiGo</a> website on this site,
so I took the opportunity to update the landing page with a mention of the project.
Me and Claude would like to see it picked up by someone, or perhaps a continuation of the project.
For now we make sure it builds with new versions of Debian and Ubuntu.
Which reminds me that I haven't pushed the changes to make it work with Ubuntu 22.04..</p>GoBiGas technical coefficients2022-06-20T16:30:13+02:002022-06-20T16:30:13+02:00tomastag:www.härdin.se,2022-06-20:/blog/2022/06/20/gobigas-technical-coefficients/<p><a href="http://www.härdin.se/images/gobigas/-000.jpg"><img alt="Picture of the GiBoGas plant" src="http://www.härdin.se/images/gobigas/t-000.jpg"></a></p>
<p>I recently learned of <a href="https://www.chalmers.se/hosted/cigb-en/gobigas">the GoBiGas project</a>,
an experimental <a href="https://en.wikipedia.org/wiki/Gasification">gasification</a> plant constructed by <a href="https://www.goteborgenergi.se/">Göteborg Energi</a> operated between 2014-2018 and mothballed since then.
The idea is to turn biomass in the form of wood pellets and bark into methane (CH<sub>4</sub>) at a rate of 20 MW (0.55 m³/s …</p><p><a href="http://www.härdin.se/images/gobigas/-000.jpg"><img alt="Picture of the GiBoGas plant" src="http://www.härdin.se/images/gobigas/t-000.jpg"></a></p>
<p>I recently learned of <a href="https://www.chalmers.se/hosted/cigb-en/gobigas">the GoBiGas project</a>,
an experimental <a href="https://en.wikipedia.org/wiki/Gasification">gasification</a> plant constructed by <a href="https://www.goteborgenergi.se/">Göteborg Energi</a> operated between 2014-2018 and mothballed since then.
The idea is to turn biomass in the form of wood pellets and bark into methane (CH<sub>4</sub>) at a rate of 20 MW (0.55 m³/s or 0.36 kg/s).
This ties heavily into something called <a href="https://en.wikipedia.org/wiki/Bioenergy_with_carbon_capture_and_storage">bioenergy with carbon capture and storage</a> (BECCS), which is likely to be one of many important technologies to reverse global warming.</p>
<p>Since GoBiGas is a publicly funded project, lots of useful information is available in its English-language final report <a href="https://www.goteborgenergi.se/Files/Webb20/Kategoriserad%20information/Forskningsprojekt/The%20GoBiGas%20Project%20-%20Demonstration%20of%20the%20Production%20of%20Biomethane%20from%20Biomass%20v%20230507_6_0.pdf">here</a>.
In this post I turn the in-kind data available in the report into technical coefficients.</p>
<h2>Chemistry</h2>
<p><a href="http://www.härdin.se/images/gobigas/-016.jpg"><img alt="Schematic picture of the gasification section" src="http://www.härdin.se/images/gobigas/t-016.jpg"></a></p>
<p>The gasification process can be summarized as follows:</p>
<ol>
<li>Heat dry biomass in a low-oxygen environment, releasing H<sub>2</sub> + CO (<a href="https://en.wikipedia.org/wiki/Syngas">syngas</a>) and other gasses like CO<sub>2</sub> and steam</li>
<li>Cool, dry and filter the syngas and do something useful with it</li>
<li>Besides turning into syngas, some biomass remains as carbon (C) that can be buried</li>
</ol>
<p>The mix between H<sub>2</sub>, CO<sub>x</sub> and C can be controlled by varying the amount of O<sub>2</sub> and H<sub>2</sub>O injected into the gasifier in proportion to the carbon in the biomass:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>C</mi><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>H</mi><mn>2</mn></msub><mspace width="0"/><mi>O</mi><mo lspace="0.278em" rspace="0.278em">→</mo><mi>C</mi><mspace width="0"/><mi>O</mi><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>H</mi><mn>2</mn></msub><mspace width="1.333em"/><msub><mi mathvariant="normal">Δ</mi><mi>r</mi></msub><mspace width="0"/><mi>H</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mo lspace="0" rspace="0">+</mo><mn>131</mn><mo lspace="0" rspace="0">.</mo><mn>3</mn><mspace width="0.167em"/><mtext>kJ/mol</mtext></mrow>
</math>
</span>
<span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>C</mi><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>O</mi><mn>2</mn></msub><mo lspace="0.278em" rspace="0.278em">→</mo><mi>C</mi><mspace width="0"/><msub><mi>O</mi><mn>2</mn></msub><mspace width="1.333em"/><msub><mi mathvariant="normal">Δ</mi><mi>r</mi></msub><mspace width="0"/><mi>H</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mo lspace="0" rspace="0">-</mo><mn>393</mn><mo lspace="0" rspace="0">.</mo><mn>5</mn><mspace width="0.167em"/><mtext>kJ/mol</mtext></mrow>
</math>
</span></p>
<p>Note that the reduction of H<sub>2</sub>O to H<sub>2</sub> + O<sup>2-</sup> is endothermic.
Obviously the less water and oxygen that is injected the more carbon is produced.
The biomass itself contains oxygen and hydrogen chemically bound in cellulose and lignin, and water as moisture.
It is beneficial to dry the biomass prior to gasification, both in case of biochar production but also for gasification as the report reveals.</p>
<p><a href="http://www.härdin.se/images/gobigas/-012.jpg"><img alt="Picture of the GiBoGas plant" src="http://www.härdin.se/images/gobigas/t-012.jpg"></a></p>
<p>In the GoBiGas plant the syngas is turned into CH<sub>4</sub> by hydrogenating the CO<sub>x</sub> gas.
This is done in the methanation section shown in figure 2.5 in the report.
These chemical processes can be summed up as:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>C</mi><mspace width="0"/><mi>O</mi><mo lspace="0.222em" rspace="0.222em">+</mo><mn>3</mn><msub><mi>H</mi><mn>2</mn></msub><mo lspace="0.278em" rspace="0.278em">→</mo><mi>C</mi><mspace width="0"/><msub><mi>H</mi><mn>4</mn></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>H</mi><mn>2</mn></msub><mspace width="0"/><mi>O</mi><mspace width="1.333em"/><msub><mi mathvariant="normal">Δ</mi><mi>r</mi></msub><mspace width="0"/><mi>H</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mo lspace="0" rspace="0">-</mo><mn>206</mn><mspace width="0.167em"/><mtext>kJ/mol</mtext></mrow>
</math>
</span>
<span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>C</mi><mspace width="0"/><msub><mi>O</mi><mn>2</mn></msub><mo lspace="0.222em" rspace="0.222em">+</mo><mn>4</mn><msub><mi>H</mi><mn>2</mn></msub><mo lspace="0.278em" rspace="0.278em">→</mo><mi>C</mi><mspace width="0"/><msub><mi>H</mi><mn>4</mn></msub><mo lspace="0.222em" rspace="0.222em">+</mo><mn>2</mn><msub><mi>H</mi><mn>2</mn></msub><mspace width="0"/><mi>O</mi><mspace width="1.333em"/><msub><mi mathvariant="normal">Δ</mi><mi>r</mi></msub><mspace width="0"/><mi>H</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mo lspace="0" rspace="0">-</mo><mn>164</mn><mspace width="0.167em"/><mtext>kJ/mol</mtext></mrow>
</math>
</span></p>
<p>Alternatives to methanation are burning the syngas or turning it into oil in a <a href="https://en.wikipedia.org/wiki/Fischer%E2%80%93Tropsch_process">Fischer-Tropsch reactor</a>.
The latter is useful as an alternative to liquid fossil fuels.</p>
<p>Extra H<sub>2</sub> could be supplied via for example electrolysis of water, resulting in more hydrocarbons and less CO<sub>2</sub>, if the electricity comes from a fossil free source like on-site photovoltaics.</p>
<p>The plant also produces various other chemicals as byproducts including BTX (benzene, toluene and xylenes).
These are useful in their own right, but are presently simply fed back into the reactor and burned.</p>
<h3>Solar gasification</h3>
<p><a href="http://www.härdin.se/images/gobigas/-Parkent_BSP.jpg"><img alt="Picture of the solar furnace of Uzbekistan" src="http://www.härdin.se/images/gobigas/t-Parkent_BSP.jpg"></a></p>
<p>The heat for the gasification step can come from anywhere, so long as it is of high enough temperature (> 700°C).
In the GoBiGas plant part of the feedstock is burned for this purpose, releasing CO<sub>2</sub>.
The report reveals that as much as 70% of the carbon is wasted in this way.
If solar heat is used instead then the carbon sequestration potential increases.
If my calculations are correct then these 70% correspond to somewhere between 24-28 MW of heat.
Assuming a solar constant of 1 kW/m² this is no more than 2.8 ha of (normal) solar collecting area.</p>
<p>A plant utilizing solar heat has the potential to be superior to more low-tech alternatives like <a href="https://en.wikipedia.org/wiki/Slash-and-char">slash-and-char</a>.</p>
<h2>Economics</h2>
<p>Gasification can be carbon negative, especially if done together with comprehensive economic planning.
The GoBiGas plant is merely carbon neutral.
Furthermore it is limited by being embedded in bourgeois society.
This limitation is revealed in <a href="https://www.goteborgenergi.se/om-oss/vad-vi-gor/forskning-utveckling/gobigas">the project's page on the Göteborg Energi website</a>:</p>
<blockquote>
<p>The plans for the second stage were shelved in 2015 when the biogas market had not reached the development that was forecasted in order to reach profitability in the project. </p>
</blockquote>
<p>In other words: new public management demands that even efforts toward climate change <em>mitigation</em> be subservient to the whims of the market.
Nevermind climate change <em>reversal</em>.</p>
<h2>Technical coefficients</h2>
<p>For working out the technical coefficients we need to know what temporal granularity we're after.
The plant has a start-up time of "a couple of days" (section 3.5) or "5–7 days" (chapter 18).
Whatever the number, this is a non-convexity as far as planning goes.
Regular maintenance would have to be scheduled, and it would likely be beneficial if the plan solver had the flexibility of setting the maintenance schedule within given constraints.
For now I presume steady-state operation.</p>
<p><a href="https://www.gp.se/nyheter/g%C3%B6teborg/anst%C3%A4llda-flyr-gobigas-1.108608">At least three people were required to run the plant</a>.
Despite the poor work environment with so few people, I will use this number for lack of a better one.
Three people per shift means that each hour corresponds to 10,800 worker seconds.
Section 3.4 of the report provides information on consumables from which we can construct the following table:</p>
<table>
<tr><th>What</th><th>Amount</th><th>Unit</th><th>Comment</th></tr>
<tr><td>Wood pellets</td><td>-600</td><td>g</td><td>120*12/16/0.3/0.5</td></tr>
<tr><td>Electricity</td><td>-733</td><td>kJ</td><td> </td></tr>
<tr><td>H<sub>2</sub>O</td><td>-450.06</td><td>g</td><td>(-(<abbr title="fresh water">4e6</abbr>+<abbr title="process water">1e6</abbr>+<abbr title="K2CO3 solution">6e3*1.415</abbr>)+<abbr title="steam production">100e3*0.657/16*2*18)/3600/3</abbr></td></tr>
<tr><td>CaCO<sub>3</sub></td><td>-11.111</td><td>g</td><td>Product gas filter</td></tr>
<tr><td>RME</td><td>-6.4815</td><td>g</td><td>Biodiesel in tar scrubber</td></tr>
<tr><td>Olivine</td><td>-6.0185</td><td>g</td><td>Potassium-activated olivine</td></tr>
<tr><td>K<sub>2</sub>CO<sub>3</sub></td><td>-0.5241</td><td>g</td><td>40% by mass -> <a href="https://www.engineeringtoolbox.com/density-aqueous-solution-inorganic-potassium-salt-concentration-d_1956.html">1.415 kg/l</a></td></tr>
<tr><td>N<sub>2</sub></td><td>-0.4632</td><td>g</td><td>Purge gas</td></tr>
<tr><td>Ash</td><td>+17.13</td><td>g</td><td> </td></tr>
<tr><td>CH<sub>4</sub></td><td>+120</td><td>g</td><td>Net output, 360/3, 20/3 = 6.67 MW</td></tr>
<tr><td>CO<sub>2</sub></td><td>+786.73</td><td>g</td><td><abbr title="gasifier">600*0.5*0.7*44/12</abbr> + <abbr title="steam production">100e3*0.657/3600/3*44/16</abbr></td></tr>
</table>
<p>Where the table in the report has a range of values I have used the larger values in all cases.</p>
<p>The wood pellet consumption figure is based on a carbon utilization of <math>
<mrow><msub><mi>μ</mi><mi>C</mi></msub><mo lspace="0.278em" rspace="0.278em">=</mo><mn>0</mn><mo lspace="0" rspace="0">.</mo><mn>3</mn></mrow>
</math> (section 3.5), the 0.36 kg/s figure at the start of this post and dry wood being 50% carbon by mass (<a href="https://www.fpl.fs.fed.us/documnts/pdf1984/pette84a.pdf">source</a>), all divided by three.
CO<sub>2</sub> is similarly based on <math>
<mrow><mn>1</mn><mo lspace="0.222em" rspace="0.222em">-</mo><msub><mi>μ</mi><mi>C</mi></msub><mo lspace="0.278em" rspace="0.278em">=</mo><mn>0</mn><mo lspace="0" rspace="0">.</mo><mn>7</mn></mrow>
</math>.
In this <a href="https://www.youtube.com/watch?v=XuaL0XyUW2c">presentation</a> at 36:40 it is stated that the plant consumes 6 tons of fuel per hour which translates to 556 g compared to the 600 g figure above.
Close enough.</p>
<p>Some of the materials listed here, like the olivine and potassium carbonate, act as catalysts that would likely be recycled over time.
In particular the potassium acts to suppress the formation of tars.
In the presentation linked in the previous paragraph sulfur is also mentioned as a catalyst, but I find no mention of added sulfur in the report.
Presumably the biomass contains enough sulfur as is.</p>
<p>There is also waste heat that can be used for municipal heating. Making use of this heat (co-generation) supposedly brings the efficiency of the plant to 90%.</p>
<h3>Biochar</h3>
<p>As mentioned in the chemistry section, if less water and oxygen is introduced into the reactor then biochar (carbon) tends to be formed.
With an appropriately designed plant one could have a "dial" that controls how much of the biomass gets turned into hydrocarbons and how much gets turned into char.
GoBiGas is not designed for this particular use case, but for illustrative purposes I will try and guesstimate technical coefficients for this application as well.</p>
<p>The report mentions a theoretical maximum carbon utilization of <math>
<mrow><msub><mi>μ</mi><mrow><mi>C</mi><mo lspace="0" rspace="0">,</mo><mtext>theoretical</mtext></mrow></msub><mo lspace="0.278em" rspace="0.278em">=</mo><mn>0</mn><mo lspace="0" rspace="0">.</mo><mn>52</mn></mrow>
</math>.
Let's assume things work exactly like this for biochar since it makes for more interesting technical coefficients.
The reactor can be powered by the syngas given off naturally by the oxygen and hydrogen chemically bound in the fuel.
Everything coming off the fuel gets burned, including tars, so there is no need for filtration.
This removes the need for olivine and potassium carbonate as well.
Presumably process water and purge gas aren't necessary either.
This leads to a very much simpler set of technical coefficients:</p>
<table>
<tr><th>What</th><th>Amount</th><th>Unit</th><th>Comment</th></tr>
<tr><td>Wood pellets</td><td>-600</td><td>g</td><td></td></tr>
<tr><td>Ash</td><td>+17.13</td><td>g</td><td> </td></tr>
<tr><td>C</td><td>+156</td><td>g</td><td>Char, 600*0.5*0.52</td></tr>
<tr><td>H<sub>2</sub>O</td><td>+324</td><td>g</td><td>600*0.06*18/2</td></tr>
<tr><td>CO<sub>2</sub></td><td>+528</td><td>g</td><td>600*0.5*0.48*44/12</td></tr>
</table>
<p>There is a mass discrepancy in this table due to oxygen from the atmosphere not being accounted for.
The oxygen in the carbon dioxide and water adds up to 672 g while the wood only contains 264 g.
We could therefore if we like add a row for -408 g atmospheric O<sub>2</sub>.</p>
<h3>Combined table</h3>
<table>
<tr><th>What</th><th>x<sub>CH<sub>4</sub></sub></th><th>x<sub>C</sub></th><th>Unit</th></tr>
<tr><td>Wood pellets</td><td>-600</td><td>-600</td><td>g</td></tr>
<tr><td>Electricity</td><td>-733</td><td></td><td>kJ</td></tr>
<tr><td>H<sub>2</sub>O</td><td>-450.06</td><td>+324</td><td>g</td></tr>
<tr><td>CaCO<sub>3</sub></td><td>-11.111</td><td></td><td>g</td></tr>
<tr><td>RME</td><td>-6.4815</td><td></td><td>g</td></tr>
<tr><td>Olivine</td><td>-6.0185</td><td></td><td>g</td></tr>
<tr><td>K<sub>2</sub>CO<sub>3</sub></td><td>-0.5241</td><td></td><td>g</td></tr>
<tr><td>N<sub>2</sub></td><td>-0.4632</td><td></td><td>g</td></tr>
<tr><td>Ash</td><td>+17.13</td><td>+17.13</td><td>g</td></tr>
<tr><td>CH<sub>4</sub></td><td>+120</td><td></td><td>g</td></tr>
<tr><td>C</td><td></td><td>+156</td><td>g</td></tr>
<tr><td>CO<sub>2</sub></td><td>+786.73</td><td>+528</td><td>g</td></tr>
</table>
<p>Subject to <math>
<mrow><msub><mi>x</mi><mrow><mi>C</mi><mspace width="0"/><msub><mi>H</mi><mn>4</mn></msub></mrow></msub><mo lspace="0.278em" rspace="0.278em">≥</mo><mn>0</mn></mrow>
</math>, <math>
<mrow><msub><mi>x</mi><mi>C</mi></msub><mo lspace="0.278em" rspace="0.278em">≥</mo><mn>0</mn></mrow>
</math> and <math>
<mrow><msub><mi>x</mi><mrow><mi>C</mi><mspace width="0"/><msub><mi>H</mi><mn>4</mn></msub></mrow></msub><mo lspace="0.222em" rspace="0.222em">+</mo><msub><mi>x</mi><mi>C</mi></msub><mo lspace="0.278em" rspace="0.278em">≤</mo><mn>3</mn></mrow>
</math>.</p>
<h2>Biomass supply</h2>
<p>The average site productivity (bonitet) for forests in Sweden is 5.5 <abbr title="skogskubikmeter, forest cubic meters">m³sk</abbr>/(ha*y) distributed over 22,125,000 ha (<a href="https://www.slu.se/globalassets/ew/org/centrb/rt/dokument/skogsdata/skogsdata_2022_webb.pdf">SLU</a>, table 3.11a) or 122 Mm³sk/y.
This corresponds to roughly 44.7 Mton carbon or 164 Mton CO<sub>2</sub> per year if all parts of the trees are used and burned (<a href="https://www.skogssverige.se/hur-mycket-co2-tar-ett-tradm3sk-upp-under-15-ar">skogssverige.se</a>).
Sweden's emissions as of 2020 are 46.3 Mton CO<sub>2</sub> equivalent (<a href="https://www.naturvardsverket.se/data-och-statistik/klimat/vaxthusgaser-territoriella-utslapp-och-upptag">naturvardsverket.se</a>).
Clearly there is great potential here even for a country that gets comparatively little sunlight as Sweden.</p>
<p>Some readers might object that most of these trees get turned into useful lumber that shouldn't be burned or charred, and they'd almost certainly be right.
But eventually that lumber turns into scrap wood which is burned at present rather than charred.
So when looking at the whole lifecycle of forest products it appears that a net sequestration of <math>
<mrow><mn>44</mn><mo lspace="0" rspace="0">.</mo><mn>7</mn><mo lspace="0.222em" rspace="0.222em">*</mo><mn>0</mn><mo lspace="0" rspace="0">.</mo><mn>52</mn><mo lspace="0.222em" rspace="0.222em">*</mo><mn>44</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>12</mn><mo lspace="0.278em" rspace="0.278em">=</mo><mn>85</mn><mo lspace="0" rspace="0">.</mo><mn>2</mn></mrow>
</math> Mton CO<sub>2</sub> per year may be possible, which is clearly more than 46.3 Mton.
There is even enough room there to turn some of the wood into biofuel.</p>
<p>Finally there are other potential sources of biomass.
Hemp in particular seems able to sequester 20 tons of CO<sub>2</sub> per hectare per harvest (<a href="https://www2.jordbruksverket.se/webdav/files/SJV/trycksaker/Pdf_jo/jo06_5.pdf">jordbruksverket.se</a>, <a href="https://hemp.inc/carbon-sequestration-how-hemp-can-help-save-the-world/">hemp.inc</a>) compared to wood's <math>
<mrow><mn>5</mn><mo lspace="0" rspace="0">.</mo><mn>5</mn><mo lspace="0.222em" rspace="0.222em">*</mo><mn>0</mn><mo lspace="0" rspace="0">.</mo><mn>735</mn><mo lspace="0.222em" rspace="0.222em">*</mo><mn>0</mn><mo lspace="0" rspace="0">.</mo><mn>5</mn><mo lspace="0.222em" rspace="0.222em">*</mo><mn>44</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>12</mn><mo lspace="0.278em" rspace="0.278em">=</mo><mn>7</mn><mo lspace="0" rspace="0">.</mo><mn>4</mn></mrow>
</math> tons/(ha*y).
Unfortunately the powers that be in Sweden hate hemp and do all in their power to defy legalization directives from the EU.</p>
<p>Addendum (2022-06-23): I see in my notes that algea is another possibility which I think I should bring up here.
<a href="https://www.massey.ac.nz/~ychisti/Biodiesel.pdf">This paper</a> by Yusuf Chisti suggests that CO<sub>2</sub> sequestration could be as high as 50 t/(ha*y) in an algea farm.
Optimal bioractor design is still somewhat of an open question.
But a simpler alternative might be possible: harvesting algal blooms.
This would have a dual benefit: sequestering greenhouse gasses and reversing eutrophication.
Various systems for doing this already exist on the market.
The resulting algal sludge can be further dried in the sun and then gasified.</p>
<h2>News articles, seminars and other material</h2>
<p>There is a bunch of coverage of the GoBiGas project, some positive, some negative and some inbetween.
Most of these are in Swedish. I have translated the titles to English.
There are more articles than these but they were paywalled and so I have not linked them.</p>
<ul>
<li><a href="https://www.gp.se/nyheter/g%C3%B6teborg/anst%C3%A4llda-flyr-gobigas-1.108608">Anställda flyr Gobigas</a> (<em>Employees flee Gobigas</em>), Göteborgsposten, 2015-06-29</li>
<li><a href="https://www.gp.se/debatt/gobigas-en-del-av-l%C3%B6sningen-1.175661">Gobigas en del av lösningen</a> (<em>Gobigas a part of the solution</em>), Göteborgsposten, 2015-12-12</li>
<li><a href="https://www.youtube.com/watch?v=XuaL0XyUW2c">GoBiGas – Framtiden eller fiasko av episka proportioner</a> (<em>GoBiGas – The future or failure of epic proportions</em>), YouTube (<a href="https://vid.puffyan.us/watch?v=XuaL0XyUW2c">invidious link</a>), 2017-02-21</li>
<li><a href="https://www.ieabioenergy.com/wp-content/uploads/2018/06/GoBiGas_Webinar_20_june_final.pdf">GoBiGas: An Industry Relevant State-of-The-Art Reference for Advanced Biofuel Production via Gasification</a>, slides for part of the above video, in English</li>
<li><a href="https://www.etc.se/inrikes/gobigas-satsningen-som-kom-av-sig">Gobigas - satsningen som kom av sig</a> (<em>Gobigas - the investment that floundered</em>), ETC, 2017-06-15</li>
<li><a href="https://www.svt.se/nyheter/lokalt/vast/investerade-nastan-tva-miljarder-i-biogasanlaggning-nu-laggs-projektet-ner">Investerade nästan två miljarder i Gobigas – nu läggs projektet ner</a> (<em>Invested nearly two billion SEK (200M USD) in GoBiGas – now the project is being shut down</em>), Sveriges Television, 2018-04-03</li>
<li><a href="https://www.svt.se/nyheter/lokalt/vast/gobigas-projektet-en-succe">Professor: ”Gobigas-projektet en teknisk succé”</a> (<em>Professor: ”The GoBiGas project a technological success”</em>), Sveriges Television, 2018-04-04</li>
<li><a href="https://www.gp.se/debatt/%C3%A5teruppstarta-gobigas-och-fasa-ut-beroendet-av-rysk-gas-1.73334121">Återuppstarta GoBiGas och fasa ut beroendet av rysk gas</a> (<em>Restart GoBiGas and phase out the dependence on Russian gas</em>), Göteborgsposten, 2022-05-25</li>
</ul>Planning, cybernetics and socialism, part 22022-03-23T22:00:27+01:002022-03-23T22:00:27+01:00tomastag:www.härdin.se,2022-03-23:/blog/2022/03/23/planning-cybernetics-and-socialism-part-2/<video width="852" height="480" poster="http://www.härdin.se/files/videos/cyber-video-part2-v2.jpg" controls style="max-width:100%;height:auto">
<source src="http://www.härdin.se/files/videos/cyber-video-part2-v2-web.mp4" type="video/mp4"/>
<source src="http://www.härdin.se/files/videos/cyber-video-part2-v2.webm" type="video/webm"/>
Your browser does not support the video tag :(
</video>
<p>This is the second video in the two-part series I'm doing in collaboration with <a href="https://paulcockshott.wordpress.com/">Paul Cockshott</a>.</p>
<p>This video is mirrored on <a href="https://www.youtube.com/watch?v=igDq8vjRhO4">my YouTube channel</a> and on Paul's channel <a href="https://www.youtube.com/watch?v=epzSIQsadQU">here</a>.</p>Planning, cybernetics and socialism, part 12022-03-17T18:37:23+01:002022-03-17T18:37:23+01:00tomastag:www.härdin.se,2022-03-17:/blog/2022/03/17/planning-cybernetics-and-socialism-part-1/<video width="852" height="480" poster="http://www.härdin.se/files/videos/cyber-video-part1-v2.jpg" controls style="max-width:100%;height:auto">
<source src="http://www.härdin.se/files/videos/cyber-video-part1-v2-web.mp4" type="video/mp4"/>
<source src="http://www.härdin.se/files/videos/cyber-video-part1-v2.webm" type="video/webm"/>
Your browser does not support the video tag :(
</video>
<p>This is the first video in a two-part series I'm doing in collaboration with <a href="https://paulcockshott.wordpress.com/">Paul Cockshott</a>.
Expect part 2 in roughly one week.</p>
<p>This video is mirrored on <a href="https://www.youtube.com/watch?v=4F-hJanMPks">my YouTube channel</a> and also on Paul's channel <a href="https://www.youtube.com/watch?v=CJUIJ4qIk5A">here</a>.</p>web@ retired2022-02-23T19:12:21+01:002022-02-23T19:12:21+01:00tomastag:www.härdin.se,2022-02-23:/blog/2022/02/23/web-retired/<p>Due to spam I have retired the web at haerdin dot se e-mail alias and replaced it with comments at haerdin dot se.
comments@ is more generic as well, which is useful for things like YouTube.</p>Towards large scale linear planning2022-02-04T17:25:56+01:002022-02-04T17:25:56+01:00tomastag:www.härdin.se,2022-02-04:/blog/2022/02/04/towards-large-scale-linear-planning/<p>In this post I will look at how large linear programs we can expect to be solvable on a modern computer cluster.
I will only consider linear programs related to economic planning, meaning programs that are very sparse.
I will be using the local supercomputer center <a href="https://www.hpc2n.umu.se/">HPC2N</a> and its <a href="https://www.hpc2n.umu.se/resources/hardware/kebnekaise">Kebnekaise …</a></p><p>In this post I will look at how large linear programs we can expect to be solvable on a modern computer cluster.
I will only consider linear programs related to economic planning, meaning programs that are very sparse.
I will be using the local supercomputer center <a href="https://www.hpc2n.umu.se/">HPC2N</a> and its <a href="https://www.hpc2n.umu.se/resources/hardware/kebnekaise">Kebnekaise</a> cluster as my reference.
I assume the reader is familiar with the <a href="https://en.wikipedia.org/wiki/Message_Passing_Interface">Message Passing Interface (MPI)</a>.
I use the term <em>work</em> here rather than time, and it is to be understood as the total amount of computation done by all nodes.
The amount of time necessary depends on the number of nodes and how they are connected.
Similarly applies for memory as I don't always bother to specify where everything is stored, but only concern myself with the total amount of memory used by the entire cluster.</p>
<p>In <a href="http://www.härdin.se/blog/2021/02/24/planning-complexity-for-model-economies/">a previous post</a> I laid down the rough shape of the linear programs in question.
I will expand on it slightly.
Each column in the constraint matrix now represents one <em>production method</em>.
Each workplace could have many methods available.
Each column could represent one particular machine.
The average number of non-zeroes per column is bound by some constant <math>
<mi>q</mi>
</math>.</p>
<p>Let <math>
<mi>S</mi>
</math> denote the entire system matrix including non-negativity constraints and the constraint for the objective function.
Finding a solution <math>
<mrow><mi>x</mi><mo lspace="0.278em" rspace="0.278em">∈</mo><msup><mi mathvariant="double-struck">R</mi><mrow><mi>n</mi><mo lspace="0" rspace="0">×</mo><mn>1</mn></mrow></msup></mrow>
</math> that is within some given percentage of optimum involves repeatedly solving the following system</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msub><mi>H</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mspace width="0"/><msub><mi>h</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0.278em" rspace="0.278em">=</mo><msup><mi>S</mi><mi>T</mi></msup><mspace width="0"/><msubsup><mi mathvariant="normal">Λ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow><mrow><mo lspace="0" rspace="0">-</mo><mn>2</mn></mrow></msubsup><mspace width="0"/><mi>S</mi><mspace width="0"/><msub><mi>h</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0.278em" rspace="0.278em">=</mo><mo lspace="0" rspace="0">-</mo><msup><mi>S</mi><mi>T</mi></msup><mspace width="0"/><msubsup><mi mathvariant="normal">Λ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow><mrow><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow></msubsup><mn mathvariant="bold">1</mn><mo lspace="0.278em" rspace="0.278em">=</mo><mo lspace="0" rspace="0">-</mo><msub><mi>g</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub></mrow>
</math>
</span></p>
<p>where <math>
<msub><mi mathvariant="normal">Λ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math> is diagonal and changes between steps.
Sizes are as follows:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msub><mi>H</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0.278em" rspace="0.278em">∈</mo><msup><mi mathvariant="double-struck">R</mi><mrow><mi>n</mi><mo lspace="0" rspace="0">×</mo><mi>n</mi></mrow></msup><mo lspace="0" rspace="0.500em">,</mo><mi>S</mi><mo lspace="0.278em" rspace="0.278em">∈</mo><msup><mi mathvariant="double-struck">R</mi><mrow><mi>m</mi><mo lspace="0" rspace="0">×</mo><mi>n</mi></mrow></msup><mo lspace="0" rspace="0.500em">,</mo><msub><mi mathvariant="normal">Λ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0.278em" rspace="0.278em">∈</mo><msup><mi mathvariant="double-struck">R</mi><mrow><mi>m</mi><mo lspace="0" rspace="0">×</mo><mi>m</mi></mrow></msup><mo lspace="0" rspace="0.500em">,</mo><mi>m</mi><mo lspace="0.278em" rspace="0.278em">></mo><mi>n</mi></mrow>
</math>
</span></p>
<p>The number of solves necessary for <math>
<mi>L</mi>
</math> bits of precision and <math>
<mi>m</mi>
</math> constraints is somewhere between <math>
<mrow><mi>L</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>2</mn></mrow>
</math> and <math>
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>L</mi><msqrt><mi>m</mi></msqrt><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math>.
The lower bound is my own empirical result and the upper bound is due to Renegar.</p>
<p>Because the system is symmetric and positive definite, the <a href="https://en.wikipedia.org/wiki/Conjugate_gradient_method">conjugate gradient method</a> can be used.
The number of CG iterations necessary depends on how large global steps are taken. With a conservative <math>
<mi>δ</mi>
</math>, few CG iterations are necessary per solve. If lots of extrapolation is used, like always stepping 75% of the way to the nearest constraint, then a lot more CG iterations are necessary per solve. A practical solver balances these two. A cluster implementation may choose to try different step sizes in parallel, assigning each one to a subset of machines and seeing which makes the most progress.</p>
<p>For an empirical lower bound using a diagonal preconditioner and large steps I have found 2000 CG iterations to be enough.</p>
<p>For an upper bound we need to first know the number of Newton steps per bit.
Renegar tells us that each step with <math>
<mrow><mi>δ</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>13</mn><msqrt><mi>m</mi></msqrt><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> shrinks the objective function by a factor <math>
<mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0.222em" rspace="0.222em">-</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>28</mn><msqrt><mi>m</mi></msqrt><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math>.
Together with the fact that we're solving both the primal and dual programs this means <math>
<mrow><mn>56</mn><mspace width="0.167em"/><mi>ln</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>2</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><msqrt><mi>m</mi></msqrt></mrow>
</math> Newton steps per bit.
Each Newton step in turn requires some amount of CG iterations that depends on the condition number of <math>
<msub><mi>H</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math> and the quality of the preconditioner.</p>
<p>We can derive how many iterations are necessary to find the solution for each Newton step to within machine precision with single-precision floating point numbers using the following:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msup><mrow><mo stretchy="true">(</mo><mrow><mn>1</mn><mo lspace="0.222em" rspace="0.222em">-</mo><mfrac><mn>2</mn><msqrt><mi>κ</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msup><mi>M</mi><mrow><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow></msup><mspace width="0"/><msub><mi>H</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0" rspace="0" stretchy="false">)</mo></msqrt></mfrac></mrow><mo stretchy="true">)</mo></mrow><mi>j</mi></msup><mo lspace="0.278em" rspace="0.278em">=</mo><msup><mn>2</mn><mrow><mo lspace="0" rspace="0">-</mo><mn>23</mn></mrow></msup><mo lspace="0.278em" rspace="0.278em">⇒</mo><mi>j</mi><mo lspace="0.278em" rspace="0.278em">≈</mo><mfrac><mn>23</mn><mn>2</mn></mfrac><mspace width="0.167em"/><mi>ln</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>2</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><msqrt><mi>κ</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msup><mi>M</mi><mrow><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow></msup><mspace width="0"/><msub><mi>H</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0" rspace="0" stretchy="false">)</mo></msqrt><mo lspace="0.278em" rspace="0.278em">≈</mo><mn>8</mn><msqrt><mi>κ</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msup><mi>M</mi><mrow><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow></msup><mspace width="0"/><msub><mi>H</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0" rspace="0" stretchy="false">)</mo></msqrt></mrow>
</math>
</span></p>
<p>­<math>
<mi>κ</mi>
</math> computes the condition number of a matrix and <math>
<mi>M</mi>
</math> is whatever preconditioner we're using.
It is assumed <math>
<mrow><mo lspace="0" rspace="0" stretchy="false">|</mo><msub><mi>h</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0" rspace="0" stretchy="false">|</mo></mrow>
</math> does not change too much between steps.
This obviously does not hold for <math>
<msub><mi>h</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>0</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math> and therefore it likely involves more CG iterations.
Due to the nature of floating point numbers it cannot involve more than 256 times the number of CG iterations than the average <math>
<msub><mi>h</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math> does, and therefore it amortizes.</p>
<p>All this taken together we expect the number of CG iterations <math>
<msub><mi>j</mi><mtext>max</mtext></msub>
</math> to solve our linear program to <math>
<mi>L</mi>
</math> bits of accuracy to be bracketed by</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mn>2000</mn><mo lspace="0.278em" rspace="0.278em">≤</mo><msub><mi>j</mi><mtext>max</mtext></msub><mo lspace="0.278em" rspace="0.278em">≤</mo><mn>309</mn><mi>L</mi><msqrt><mi>κ</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msup><mi>M</mi><mrow><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow></msup><mspace width="0"/><mi>H</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>m</mi></msqrt></mrow>
</math>
</span></p>
<p>where <math>
<mi>κ</mi>
</math> is understood as the average condition number across all steps.</p>
<h2>Preconditioner</h2>
<p>I mentioned preconditioners earlier.
Preconditioning is an important way to speed up the conjugate gradient method.
A preconditioner is an operator that approximates the inverse of the system to be solved.
Ways of maintaining a good preconditioner is where the algorithmic progress for interior point methods occurs today.</p>
<h3>Diagonal preconditioner</h3>
<p>A diagonal preconditioner is one of the simplest preconditioners available.
It is simply the diagonal of <math>
<msub><mi>H</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math> which can be computed with <math>
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>q</mi><mspace width="0"/><mi>n</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> work and then trivially applied.
Because of its cheapness we compute it before every Newton step.</p>
<h3>Incomplete Cholesky factorization</h3>
<p>The <a href="https://en.wikipedia.org/wiki/Incomplete_Cholesky_factorization">incomplete (sparse) Cholesky factorization</a> is a much better preconditioner than the diagonal, but it is also more costly to compute.
First we will note that thanks to the structure of <math>
<mi>S</mi>
</math>, forming <math>
<msub><mi>H</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math> explicitly is not too expensive.
Assuming the non-zeroes of <math>
<mi>S</mi>
</math> are distributed uniformly randomly then by the binomial distribution it can be shown that</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>nnz</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msub><mi>H</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">≈</mo><mi>n</mi><mo lspace="0.222em" rspace="0.222em">+</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo lspace="0.222em" rspace="0.222em">-</mo><mi>n</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0.222em" rspace="0.222em">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0.222em" rspace="0.222em">-</mo><mi>q</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><mi>m</mi><msup><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>q</mi></msup><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">≈</mo><mi>n</mi><mo lspace="0.222em" rspace="0.222em">+</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo lspace="0.222em" rspace="0.222em">-</mo><mi>n</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><msup><mi>q</mi><mn>2</mn></msup><mo lspace="0" rspace="0" stretchy="false">/</mo><mi>m</mi><mo lspace="0.278em" rspace="0.278em">≈</mo><msup><mi>n</mi><mn>2</mn></msup><mspace width="0"/><msup><mi>q</mi><mn>2</mn></msup><mo lspace="0" rspace="0" stretchy="false">/</mo><mi>m</mi></mrow>
</math>
</span></p>
<p>when <math>
<mrow><mi>q</mi><mo lspace="0.278em" rspace="0.278em">≪</mo><mi>m</mi></mrow>
</math>.
The following Octave program demonstrates this:</p>
<div class="highlight"><pre><span></span><code><span class="nt">q</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nt">30</span><span class="o">;</span>
<span class="nt">for</span><span class="w"> </span><span class="nt">n</span><span class="o">=</span><span class="nt">2</span><span class="o">.^(</span><span class="nt">10</span><span class="p">:</span><span class="nd">18</span><span class="o">)</span>
<span class="w"> </span><span class="nt">m</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nt">2</span><span class="o">*</span><span class="nt">n</span><span class="o">;</span>
<span class="w"> </span><span class="nt">S</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nt">sprand</span><span class="o">(</span><span class="nt">m</span><span class="o">,</span><span class="nt">n</span><span class="o">,</span><span class="nt">q</span><span class="o">/</span><span class="nt">m</span><span class="o">);</span>
<span class="w"> </span><span class="nt">B</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nt">S</span><span class="err">'</span><span class="o">*</span><span class="nt">S</span><span class="o">;</span>
<span class="w"> </span><span class="nt">est</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nt">n</span><span class="o">^</span><span class="nt">2</span><span class="o">*</span><span class="nt">q</span><span class="o">^</span><span class="nt">2</span><span class="o">/</span><span class="nt">m</span><span class="o">;</span>
<span class="w"> </span><span class="nt">printf</span><span class="o">(</span><span class="s2">"n=%6i ratio=%f\n"</span><span class="o">,</span><span class="w"> </span><span class="nt">n</span><span class="o">,</span><span class="w"> </span><span class="nt">nnz</span><span class="o">(</span><span class="nt">B</span><span class="o">)/</span><span class="nt">est</span><span class="o">);</span>
<span class="nt">endfor</span>
</code></pre></div>
<p>Which outputs the following:</p>
<div class="highlight"><pre><span></span><code>n= 1024 ratio=0.812704
n= 2048 ratio=0.897969
n= 4096 ratio=0.948767
n= 8192 ratio=0.974487
n= 16384 ratio=0.988381
n= 32768 ratio=0.995698
n= 65536 ratio=0.998564
n=131072 ratio=1.000623
n=262144 ratio=1.001329
</code></pre></div>
<p>As <math>
<mi>n</mi>
</math> (and <math>
<mi>m</mi>
</math>) grows the estimate improves.
This means <math>
<msub><mi>H</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math> is quite sparse and memory use is <math>
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msup><mi>q</mi><mn>2</mn></msup><mspace width="0"/><mi>n</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> when <math>
<mrow><mi>n</mi><mo lspace="0.278em" rspace="0.278em">∝</mo><mi>m</mi></mrow>
</math>.
Computing it involves <math>
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>q</mi><mspace width="0"/><msup><mi>n</mi><mn>2</mn></msup><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> work.
The sparsity pattern of <math>
<msub><mi>H</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math> does not change, which means computing <math>
<msub><mi>H</mi><mn>0</mn></msub>
</math> amortizes and subsequent <math>
<msub><mi>H</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math> require only <math>
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msup><mi>q</mi><mn>3</mn></msup><mspace width="0"/><mi>n</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> work (<math>
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>q</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> per non-zero).</p>
<p>It may be possible to speed up the computation of <math>
<msub><mi>H</mi><mn>0</mn></msub>
</math> by exploiting its symmetry and the structure of <math>
<mi>S</mi>
</math>.
The columns and rows of <math>
<mi>S</mi>
</math> may be ordered and indexed such that large swaths of <math>
<msub><mi>H</mi><mn>0</mn></msub>
</math> may quickly be deduced to be zero.
It might be possible to cluster <math>
<mi>S</mi>
</math> so that most information in <math>
<msub><mi>H</mi><mn>0</mn></msub>
</math> is close to the diagonal.</p>
<p>Once we have <math>
<msub><mi>H</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math> we can use it to compute the incomplete Cholesky factorization <math>
<mrow><msub><mi>L</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mspace width="0"/><msubsup><mi>L</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow><mi>T</mi></msubsup><mo lspace="0.278em" rspace="0.278em">≈</mo><msub><mi>H</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub></mrow>
</math> with <math>
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>nnz</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>H</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>n</mi><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">=</mo><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msup><mi>q</mi><mn>2</mn></msup><mspace width="0"/><msup><mi>n</mi><mn>2</mn></msup><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> work.
Such preconditioners remain useful only for so long however, and <math>
<msub><mi>L</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math> should be recomputed as the solver progresses.
Since we're doing all this in parallel what we're really talking about is <math>
<msub><mi>L</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0">-</mo><mi>τ</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math>,
meaning Cholesky factorizations that arrive slightly "late".
We can update these "late" preconditioners with low-rank adjustments using the <a href="https://en.wikipedia.org/wiki/Woodbury_matrix_identity">Woodbury matrix identity</a>,
something that is often done in the literature on interior point methods.</p>
<p>I will only use the diagonal preconditioner for the rest of this post since it is much easier to analyze.
I found the result for the density of <math>
<mi>H</mi>
</math> useful enough to leave this section intact.</p>
<h2>Parallel CG iteration</h2>
<p>Assume a cluster of <math>
<mrow><mi>P</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mi>M</mi><mo lspace="0.222em" rspace="0.222em">×</mo><mi>N</mi></mrow>
</math> nodes.
Each CG iteration involves computing</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msub><mi>q</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0.278em" rspace="0.278em">=</mo><msup><mi>S</mi><mi>T</mi></msup><mspace width="0"/><msubsup><mi mathvariant="normal">Λ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow><mrow><mo lspace="0" rspace="0">-</mo><mn>2</mn></mrow></msubsup><mspace width="0"/><mi>S</mi><mspace width="0"/><msub><mi>p</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub></mrow>
</math>
</span></p>
<p>and applying the preconditioner</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msub><mi>z</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0.278em" rspace="0.278em">=</mo><msubsup><mi>D</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow><mrow><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow></msubsup><mspace width="0"/><msub><mi>r</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub></mrow>
</math>
</span></p>
<p>where <math>
<msub><mi>D</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math> is diagonal.
There are many ways to parallelize this.
What I show here is merely one way.
Note also that in addition to these computations there are global calls to MPI_Allreduce for scalars like <math>
<msub><mi>α</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math> and <math>
<msub><mi>β</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math>,
and some trivial node-local vector arithmetic.
This gets absorbed in the big-O notation.</p>
<h3>Splitting of matrices</h3>
<p>­<math>
<mi>S</mi>
</math> is split into blocks <math>
<msub><mi>S</mi><mrow><mi>k</mi><mo lspace="0" rspace="0">,</mo><mi>l</mi></mrow></msub>
</math>, one for each node, <math>
<mrow><mn>1</mn><mo lspace="0.278em" rspace="0.278em">≤</mo><mi>k</mi><mo lspace="0.278em" rspace="0.278em">≤</mo><mi>M</mi></mrow>
</math> and <math>
<mrow><mn>1</mn><mo lspace="0.278em" rspace="0.278em">≤</mo><mi>l</mi><mo lspace="0.278em" rspace="0.278em">≤</mo><mi>N</mi></mrow>
</math>.
Each node also has <math>
<msubsup><mi mathvariant="normal">Λ</mi><msub><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow><mi>k</mi></msub><mrow><mo lspace="0" rspace="0">-</mo><mn>2</mn></mrow></msubsup>
</math>, a block on the diagonal of <math>
<msubsup><mi mathvariant="normal">Λ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow><mrow><mo lspace="0" rspace="0">-</mo><mn>2</mn></mrow></msubsup>
</math> corresponding to the horizontal strip <math>
<msub><mi>S</mi><mrow><mi>k</mi><mo lspace="0" rspace="0">,</mo><mo lspace="0" rspace="0">*</mo></mrow></msub>
</math>.</p>
<h3>Communicators</h3>
<p>In addition to the global communicator MPI_COMM_WORLD there are two more sets of communicators: rowcomm and colcomm.
Each rowcomm groups nodes belonging to one horizontal strip of <math>
<mi>S</mi>
</math>, meaning <math>
<mrow><msub><mtext>rowcomm</mtext><mi>k</mi></msub><mo lspace="0.278em" rspace="0.278em">⇔</mo><msub><mi>S</mi><mrow><mi>k</mi><mo lspace="0" rspace="0">,</mo><mo lspace="0" rspace="0">*</mo></mrow></msub></mrow>
</math>.
For colcomm it is similar, but with vertical strips: <math>
<mrow><msub><mtext>colcomm</mtext><mi>l</mi></msub><mo lspace="0.278em" rspace="0.278em">⇔</mo><msub><mi>S</mi><mrow><mo lspace="0" rspace="0">*</mo><mo lspace="0" rspace="0">,</mo><mi>l</mi></mrow></msub></mrow>
</math>.</p>
<p><img style="display:block;width:25%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/parallel_planning/S.svg" alt="Communicators and S_{k,l}"/></p>
<h3>Computing <em>D<sub>(i)</sub></em></h3>
<p>Computing <math>
<msub><mi>D</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math> involves <math>
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>q</mi><mspace width="0"/><mi>n</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><mi>P</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> node-local work and a call to MPI_Allreduce along each colcomm.
Because the amount of work and communication is trivial and amortizes it makes no difference big-O wise.</p>
<h3>Computing <em>q<sub>(j)</sub></em></h3>
<p>For practical reasons the multiplication must be broken up into two parts that look as follows:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msub><mi>t</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0.278em" rspace="0.278em">=</mo><msubsup><mi mathvariant="normal">Λ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow><mrow><mo lspace="0" rspace="0">-</mo><mn>2</mn></mrow></msubsup><mspace width="0"/><mi>S</mi><mspace width="0"/><msub><mi>p</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub></mrow>
</math>
</span></p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msub><mi>q</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0.278em" rspace="0.278em">=</mo><msup><mi>S</mi><mi>T</mi></msup><mspace width="0"/><msub><mi>t</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub></mrow>
</math>
</span></p>
<p>Then each node performs the following series of operations:</p>
<ul>
<li><math>
<mrow><msub><mi>t</mi><mi>k</mi></msub><mo lspace="0.278em" rspace="0.278em">=</mo><msubsup><mi mathvariant="normal">Λ</mi><msub><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow><mi>k</mi></msub><mrow><mo lspace="0" rspace="0">-</mo><mn>2</mn></mrow></msubsup><mspace width="0"/><msub><mi>S</mi><mrow><mi>k</mi><mo lspace="0" rspace="0">,</mo><mi>l</mi></mrow></msub><mspace width="0"/><msub><mi>p</mi><mi>l</mi></msub></mrow>
</math></li>
<li><math>
<mrow><msub><mi>t</mi><mi>k</mi></msub><mo lspace="0.278em" rspace="0.278em">=</mo><mi>MPI</mi><mo lspace="0" rspace="0">_</mo><mi>Allreduce</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msub><mi>t</mi><mi>k</mi></msub><mo lspace="0" rspace="0.167em">,</mo><mtext>MPI_SUM</mtext><mo lspace="0" rspace="0.167em">,</mo><msub><mtext>rowcomm</mtext><mi>k</mi></msub><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math></li>
<li><math>
<mrow><msub><mi>q</mi><mi>l</mi></msub><mo lspace="0.278em" rspace="0.278em">=</mo><msubsup><mi>S</mi><mrow><mi>k</mi><mo lspace="0" rspace="0">,</mo><mi>l</mi></mrow><mi>T</mi></msubsup><mspace width="0"/><msub><mi>t</mi><mi>k</mi></msub></mrow>
</math></li>
<li><math>
<mrow><msub><mi>q</mi><mi>l</mi></msub><mo lspace="0.278em" rspace="0.278em">=</mo><mi>MPI</mi><mo lspace="0" rspace="0">_</mo><mi>Allreduce</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msub><mi>q</mi><mi>l</mi></msub><mo lspace="0" rspace="0.167em">,</mo><mtext>MPI_SUM</mtext><mo lspace="0" rspace="0.167em">,</mo><mtext>colcomm</mtext><msub><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>l</mi></msub><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math></li>
</ul>
<p>Note how each communicator only has to deal with a subset of <math>
<mi>t</mi>
</math> and <math>
<mi>q</mi>
</math>.
This turns out to be important for being able to scale the system up.</p>
<h3>Complexity</h3>
<p>The amount of computation per node is <math>
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>nnz</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>S</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0" stretchy="false">/</mo><mi>P</mi><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">=</mo><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>q</mi><mspace width="0"/><mi>n</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><mi>P</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> assuming <math>
<mi>S</mi>
</math> is perfectly split up among them.
This can usually be accomplished by swapping rows and/or columns and adjsting the shape of the grid.</p>
<p>For communication we need to know how MPI_Allreduce works.
A pessimistic estimate is that it is implemented by pairwise summing in a hypercube grid.
In each rowcomm <math>
<msub><mi>t</mi><mi>k</mi></msub>
</math> is summed in <math>
<mrow><msub><mi>log</mi><mn>2</mn></msub><mspace width="0.167em"/><mi>N</mi></mrow>
</math> exchanges, each one involving <math>
<mrow><mi>m</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><mi>M</mi></mrow>
</math> elements.
Similarly with colcomm.
Let <math>
<mi>K</mi>
</math> be the time necessary to transmit one value between two nodes in the cluster, in seconds.
Then the time used by each pair of MPI_Allreduce calls is <math>
<mrow><mi>K</mi><mspace width="0"/><mi>m</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><mi>M</mi><mspace width="0.167em"/><msub><mi>log</mi><mn>2</mn></msub><mspace width="0.167em"/><mi>N</mi><mo lspace="0.222em" rspace="0.222em">+</mo><mi>K</mi><mspace width="0"/><mi>n</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><mi>N</mi><mspace width="0.167em"/><msub><mi>log</mi><mn>2</mn></msub><mspace width="0.167em"/><mi>M</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math>.</p>
<p>If we take the above, let <math>
<mrow><mi>M</mi><mo lspace="0.278em" rspace="0.278em">≈</mo><mi>N</mi><mo lspace="0.278em" rspace="0.278em">≈</mo><msqrt><mi>P</mi></msqrt></mrow>
</math> then we get the following overall complexity:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>q</mi><mspace width="0"/><mi>n</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><mi>P</mi><mo lspace="0.222em" rspace="0.222em">+</mo><mi>K</mi><mspace width="0"/><mi>n</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><msqrt><mi>P</mi></msqrt><mspace width="0.167em"/><mi>log</mi><mspace width="0.167em"/><mi>P</mi><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">=</mo><mover><mi>O</mi><mo stretchy="false" accent="true">˜</mo></mover><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>q</mi><mspace width="0"/><mi>n</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><mi>P</mi><mo lspace="0.222em" rspace="0.222em">+</mo><mi>K</mi><mspace width="0"/><mi>n</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><msqrt><mi>P</mi></msqrt><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math>
</span></p>
<p>We therefore expect linear speedup for small clusters, transitioning into <math>
<msqrt><mi>P</mi></msqrt>
</math> speedup for large clusters.</p>
<h2>Strip based splitting</h2>
<p>Another possibility of splitting <math>
<mi>S</mi>
</math> is into horizontal and vertical strips, <math>
<msub><mi>S</mi><mrow><mi>k</mi><mo lspace="0" rspace="0">,</mo><mo lspace="0" rspace="0">*</mo></mrow></msub>
</math> and <math>
<msub><mi>S</mi><mrow><mo lspace="0" rspace="0">*</mo><mo lspace="0" rspace="0">,</mo><mi>l</mi></mrow></msub>
</math> respectively.
This turns out to be worse than the method presented above except for very small clusters.
I therefore only present it in short.</p>
<p>The per-node operations look as follows:</p>
<ul>
<li><math>
<mrow><msub><mi>t</mi><mi>k</mi></msub><mo lspace="0.278em" rspace="0.278em">=</mo><msubsup><mi mathvariant="normal">Λ</mi><msub><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow><mi>k</mi></msub><mrow><mo lspace="0" rspace="0">-</mo><mn>2</mn></mrow></msubsup><mspace width="0"/><msub><mi>S</mi><mrow><mi>k</mi><mo lspace="0" rspace="0">,</mo><mo lspace="0" rspace="0">*</mo></mrow></msub><mspace width="0"/><msub><mi>p</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub></mrow>
</math></li>
<li><math>
<mrow><msub><mi>t</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0.278em" rspace="0.278em">=</mo><mi>MPI</mi><mo lspace="0" rspace="0">_</mo><mi>Allgather</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msub><mi>t</mi><mi>k</mi></msub><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math></li>
<li><math>
<mrow><msub><mi>q</mi><mi>l</mi></msub><mo lspace="0.278em" rspace="0.278em">=</mo><msubsup><mi>S</mi><mrow><mo lspace="0" rspace="0">*</mo><mo lspace="0" rspace="0">,</mo><mi>l</mi></mrow><mi>T</mi></msubsup><mspace width="0"/><msub><mi>t</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub></mrow>
</math></li>
<li><math>
<mrow><msub><mi>q</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0.278em" rspace="0.278em">=</mo><mi>MPI</mi><mo lspace="0" rspace="0">_</mo><mi>Allgather</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msub><mi>q</mi><mi>l</mi></msub><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math></li>
</ul>
<p>This means <math>
<msub><mi>t</mi><mi>k</mi></msub>
</math> and <math>
<msub><mi>q</mi><mi>l</mi></msub>
</math> are computed at each node and then MPI_Allgather'd into <math>
<msub><mi>t</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math> and <math>
<msub><mi>q</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>j</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math> on all nodes.
Allgather is assumed to be implemented by pairwise exchange of exponentially growing collections of <math>
<msub><mi>t</mi><mi>k</mi></msub>
</math>'s.
The resulting complexity is as follows:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>O</mi><mspace width="0.167em"/><mrow><mo stretchy="true">(</mo><mrow><mi>q</mi><mspace width="0"/><mi>n</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><mi>P</mi><mo lspace="0.222em" rspace="0.222em">+</mo><mi>K</mi><munderover><mo lspace="0.167em" rspace="0.167em" stretchy="false" movablelimits="false">∑</mo><mrow><mi>k</mi><mo lspace="0" rspace="0">=</mo><mn>0</mn></mrow><mrow><msub><mi>log</mi><mn>2</mn></msub><mspace width="0.167em"/><mi>P</mi></mrow></munderover><msup><mn>2</mn><mi>k</mi></msup><mi>n</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><mi>P</mi></mrow><mo stretchy="true">)</mo></mrow><mo lspace="0.278em" rspace="0.278em">=</mo><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>q</mi><mspace width="0"/><mi>n</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><mi>P</mi><mo lspace="0.222em" rspace="0.222em">+</mo><mi>K</mi><mspace width="0"/><mi>n</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math>
</span></p>
<p>This is clearly worse than the blocklevel splitting presented earlier, except when <math>
<mi>P</mi>
</math> is very small and <math>
<mrow><msub><mi>log</mi><mn>2</mn></msub><mspace width="0.167em"/><mi>P</mi></mrow>
</math> dominates.
Another way to view the communication bound is that every node must receive <math>
<mrow><mi>n</mi><mo lspace="0.222em" rspace="0.222em">+</mo><mi>m</mi></mrow>
</math> elements per iteration which clearly takes <math>
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>K</mi><mspace width="0"/><mi>n</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> time.</p>
<h2>Results</h2>
<p>The following table summarizes my estimates for how large systems can be solved on <a href="https://www.hpc2n.umu.se/resources/hardware/kebnekaise">Kebnekaise</a> for three of the node types in the cluster: Skylake, Compute-skylake and Large Memory.
For those interested in the details the LibreOffice spreadsheet used can be downloaded <a href="http://www.härdin.se/files/parallel_planning/kebnekaise.ods">here</a>.
I have chosen the average number of non-zeros per column to be <math>
<mrow><mi>q</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>160</mn></mrow>
</math> just like in previous posts, meaning the number of inputs and outputs per production method.</p>
<table>
<tr><th></th><th>Compute</th><th>Compute-skylake</th><th>Large Memory</th></tr>
<tr><th>M (#horizontal strips)</th><td>28</td><td>10</td><td>6</td></tr>
<tr><th>N (#vertical strips)</th><td>14</td><td>5</td><td>3</td></tr>
<tr><th>P (#nodes, M*N)</th><td>392</td><td>50</td><td>18</td></tr>
<tr><th>m (#constraints)</th><td>46*10⁹</td><td>12*10⁹</td><td>79*10⁹</td></tr>
<tr><th>n (#variables)</th><td>23*10⁹</td><td>6.2*10⁹</td><td>39*10⁹</td></tr>
<tr><th>Estimated CG iteration time (s)</th><td>9.25</td><td>3.28</td><td>29.45</td></tr>
</table>
<p>Keep in mind these are estimates.
To truly test this I would need to apply for a small project allocation via <a href="https://www.snic.se/">SNIC</a>.</p>
<p>The most fruitful appears to be the Compute nodes which are capable of handling 23,000,000,000 variables in less than ten seconds per iteration.
With the previously stated 2000 empirical iterations per solve this amounts to five hours of computation time.
Very comfortable.
Most of this is just sending data around.
Only ~5% of the time is spent actually computing.
This suggests that a cluster optimized for this kind of problem should have a much faster interconnect.</p>
<p>The upper bound is trickier since we don't know the condition number <math>
<mrow><mi>κ</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msup><mi>D</mi><mrow><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow></msup><mspace width="0"/><mi>H</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math>. Let's guess it is 1000. In that case the number of iterations for 7 bits of accuracy is 15 billion, or 4300 years (!).
Clearly we hope that <math>
<mi>S</mi>
</math> is not structured so that predictor-corrector methods cannot be used or else plans of this size cannot be computed even with exascale clusters.</p>
<p>One thing to keep in mind is that we are likely to reuse previous solutions, and only perturbing the system in ways like tightening/slackening constraints or adding/removing production methods.
Solving such a perturbed system is much cheaper than what has been presented here.</p>
<p>For those curious how long a post like this takes to write, I started writing this one on 2022-01-25. So about a week and a half off and on.</p>
<h2>Addendum (2022-02-07)</h2>
<p>After going through the literature some more I came across the paper <a href="https://www.researchgate.net/publication/226495491_A_lower_bound_on_the_number_of_iterations_of_long-step_primal-dual_linear_programming_algorithms"><em>A lower bound on the number of iterations of long-step primal-dual linear programming algorithms</em></a> (<a href="doi:10.1007/BF02206818">doi:10.1007/BF02206818</a>) by Michael J. Todd and Yinyu Ye which provides a worst-case bound on the number of predictor-corrector steps of <math>
<mrow><mi mathvariant="normal">Ω</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mroot><mi>m</mi><mn>3</mn></mroot><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math>.
If I understand their results correctly then the duality gap shrinks by a factor of 3 every <math>
<mrow><mi>K</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mo lspace="0" rspace="0" stretchy="false">⌊</mo><mo lspace="0" rspace="0">min</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>δ</mi><mroot><mi>m</mi><mn>3</mn></mroot><mo lspace="0" rspace="0.167em">,</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0.222em" rspace="0.222em">-</mo><mi>γ</mi><msup><mo lspace="0" rspace="0" stretchy="false">)</mo><mn>2</mn></msup><mi>n</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>8</mn><mi>α</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0" stretchy="false">⌋</mo></mrow>
</math> steps where <math>
<mrow><mi>δ</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>25</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>32</mn><mi>α</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math>, <math>
<mrow><mi>α</mi><mo lspace="0.278em" rspace="0.278em">≥</mo><mn>4</mn></mrow>
</math> and <math>
<mrow><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>2</mn><mo lspace="0.278em" rspace="0.278em"><</mo><mi>γ</mi><mo lspace="0.278em" rspace="0.278em"><</mo><mn>1</mn></mrow>
</math>.
For sufficiently large linear programs this simplifies to <math>
<mrow><mi>K</mi><mo lspace="0.278em" rspace="0.278em">≤</mo><mn>25</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>128</mn><mroot><mi>m</mi><mn>3</mn></mroot></mrow>
</math>.
Combining this with previous results in here we get:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msub><mi>j</mi><mrow><mi>m</mi><mspace width="0"/><mi>a</mi><mspace width="0"/><mi>x</mi></mrow></msub><mo lspace="0.278em" rspace="0.278em">≤</mo><mn>25</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>16</mn><mspace width="0.167em"/><msub><mi>log</mi><mn>2</mn></msub><mspace width="0.167em"/><mn>3</mn><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>L</mi><mroot><mi>m</mi><mn>3</mn></mroot><msqrt><mi>κ</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msup><mi>M</mi><mrow><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow></msup><mspace width="0"/><mi>H</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></msqrt></mrow>
</math>
</span></p>
<p>Using the same <math>
<mrow><mi>κ</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1000</mn></mrow>
</math> guess and <math>
<mrow><mi>L</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>7</mn></mrow>
</math> bits we get 780,000 iterations or 84 days. Not bad!
Keep in mind this is an upper bound. In practice predictor-corrector does even better.</p>
<p>I've also been reading up on <a href="http://www-personal.umich.edu/~murty/">Katta Murty</a>'s sphere methods.
The zero-radius version is identical to an idea I had that appeared to run in <math>
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msup><mi>n</mi><mrow><mi>ω</mi><mo lspace="0" rspace="0">+</mo><mn>1</mn></mrow></msup><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> (strongly polynomial) time.
I couldn't prove this, and by studying Murty's references I came across one paper that proves it takes exponential time for certain types of linear programs, just like the simplex method. Bummer.</p>
<p>Murty's more sophisticated sphere methods are based on a centering strategy that involves only projection and linear programs in two dimensions.
They involve very few if any matrix inversions / linear system solves.
But the number of steps appears to be up to <math>
<mrow><mn>2</mn><mi>m</mi></mrow>
</math> which may be prohibitive communication-wise even if the steps themselves are cheap.</p>On vertical integration2022-01-21T14:32:45+01:002022-01-21T14:32:45+01:00tomastag:www.härdin.se,2022-01-21:/blog/2022/01/21/on-vertical-integration/<p>Recently I have been thinking about vertically integrated values.
This has led me to some interesting observations which I will present in this post.
If you don't know what vertical integration is in the context of political economy, it is the value added to some good not just when it …</p><p>Recently I have been thinking about vertically integrated values.
This has led me to some interesting observations which I will present in this post.
If you don't know what vertical integration is in the context of political economy, it is the value added to some good not just when it is produced, but the value added to all goods from which that good is made, all the way up the production chain.</p>
<p>Let's start with the <a href="https://en.wikipedia.org/wiki/Input%E2%80%93output_model">input-output model</a> invented by Wassily Leontief.
We have a matrix <math>
<mi>A</mi>
</math> of technical coefficients specifying how much is required on average to produce one unit of each good in arbitrary units.
The columns of <math>
<mi>A</mi>
</math> represent the requirements (inputs) of each industry.
The rows of <math>
<mi>A</mi>
</math> represent where the output of each industry goes.</p>
<p>For a given demand vector <math>
<mi>d</mi>
</math> we seek the vector of gross output <math>
<mi>x</mi>
</math> required to fulfill demand.
This gives the following relation:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>x</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mi>A</mi><mspace width="0"/><mi>x</mi><mo lspace="0.222em" rspace="0.222em">+</mo><mi>d</mi></mrow>
</math>
</span></p>
<p>In other words gross output must equal what is required to produce said output plus final demand.
After rearranging we get the well-known system</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>I</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mi>A</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>x</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mi>d</mi></mrow>
</math>
</span></p>
<p>which can be solved by iterative methods.
This kind of solution is used in input-output planning, a less powerful method of planning compared to linear programming.
An LP solution can be "converted" to a Leontief solution by aggregating all units in a single industry.</p>
<p>We can use a method similar to Leontief's to find a valuation row vector <math>
<msup><mi>v</mi><mi>T</mi></msup>
</math> given a row vector <math>
<msup><mi>l</mi><mi>T</mi></msup>
</math> of value added directly in each sector:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msup><mi>v</mi><mi>T</mi></msup><mo lspace="0.278em" rspace="0.278em">=</mo><msup><mi>v</mi><mi>T</mi></msup><mspace width="0"/><mi>A</mi><mo lspace="0.222em" rspace="0.222em">+</mo><msup><mi>l</mi><mi>T</mi></msup></mrow>
</math>
</span></p>
<p>The value of each good must equal the cost of production (<math>
<mrow><msup><mi>v</mi><mi>T</mi></msup><mspace width="0"/><mi>A</mi></mrow>
</math>) plus value added (<math>
<msup><mi>l</mi><mi>T</mi></msup>
</math>).
The rearranged system is similar to the one for finding <math>
<mi>x</mi>
</math>, but transposed:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msup><mi>v</mi><mi>T</mi></msup><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>I</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mi>A</mi><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">=</mo><msup><mi>l</mi><mi>T</mi></msup></mrow>
</math>
</span></p>
<p>­<math>
<msup><mi>v</mi><mi>T</mi></msup>
</math> is what the literature calls vertically integrated (labour) values.
What is interesting about this equation is that we can choose any "value addition" vector in place of <math>
<msup><mi>l</mi><mi>T</mi></msup>
</math> and get a corresponding vertically integrated valuation vector.
If we were physiocrats or Georgists then we would choose land in units of hectare-years as the value added in production.
Each good then has some amount of land embodied in it, including the land for the factories that refined the ingredients required to make it.
Other possible valuations include greenhouse gas emissions, transportation distance, production time, energy and entropy.
Such valuations could be printed on the labels of goods.</p>
<p>Note that most of these quantities are not values in the classical sense.
Land does not enter into social relations with other land.
Only labour does.</p>
<p>Another interesting property of these equations is that we should be able to reverse engineer how capital values specific things (<math>
<msup><mi>r</mi><mi>T</mi></msup>
</math>) based on observed prices (<math>
<msup><mi>p</mi><mi>T</mi></msup>
</math>):</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msup><mi>r</mi><mi>T</mi></msup><mo lspace="0.278em" rspace="0.278em">=</mo><msup><mi>p</mi><mi>T</mi></msup><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>I</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mi>A</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math>
</span></p>
<p>For this to work we need to know <math>
<mi>A</mi>
</math>, which unfortunately we don't. Such data are company secrets.
But if we did know <math>
<mi>A</mi>
</math> then this relation means:
the value added in each industry is the price of the good produced by that industry minus the price of its constituent goods.
This fact is obvious to anyone who has ever had to bookkeep <a href="https://en.wikipedia.org/wiki/Value-added_tax">VAT</a>.</p>
<h2>Computational concerns</h2>
<p>A "richer" equation can be obtained by substituting <math>
<msup><mi>v</mi><mi>T</mi></msup>
</math> and <math>
<msup><mi>l</mi><mi>T</mi></msup>
</math> for the matrices <math>
<msup><mi>V</mi><mi>T</mi></msup>
</math> and <math>
<msup><mi>L</mi><mi>T</mi></msup>
</math> containing a multitude of valuations that we are interested in:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msup><mi>V</mi><mi>T</mi></msup><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>I</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mi>A</mi><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">=</mo><msup><mi>L</mi><mi>T</mi></msup></mrow>
</math>
</span></p>
<p>The use of matrices has implications for computation.
If enough valuations are to be computed then rather than solving each valuation separately, it makes sense to exploit the Neumann series:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>I</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mi>A</mi><msup><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mrow><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow></msup><mo lspace="0" rspace="0.278em">=</mo><munderover><mo lspace="0" rspace="0.167em" stretchy="false" movablelimits="false">∑</mo><mrow><mi>k</mi><mo lspace="0" rspace="0">=</mo><mn>0</mn></mrow><mi mathvariant="normal">∞</mi></munderover><msup><mi>A</mi><mi>k</mi></msup></mrow>
</math>
</span></p>
<p>This because matrix multiplication is sub-cubic.
­<math>
<mi>A</mi>
</math> being sparse modifies this a bit, but I still suspect the above is worthwhile.</p>
<h2>Derived quantities</h2>
<p>The scalar products of the vectors derived earlier give some useful scalar quantities.</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msup><mi>v</mi><mi>T</mi></msup><mspace width="0"/><mi>x</mi><mo lspace="0.278em" rspace="0.278em">=</mo><msup><mi>l</mi><mi>T</mi></msup><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>I</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mi>A</mi><msup><mo lspace="0" rspace="0" stretchy="false">)</mo><mrow><mo lspace="0" rspace="0">-</mo><mn>2</mn></mrow></msup><mi>d</mi></mrow>
</math>
</span></p>
<p>The sum of the values of all commodities multiplied by the mass of each commodity.
This should equal the total amount of labour employed in the entire economy.</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msup><mi>l</mi><mi>T</mi></msup><mspace width="0"/><mi>x</mi><mo lspace="0.278em" rspace="0.278em">=</mo><msup><mi>l</mi><mi>T</mi></msup><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>I</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mi>A</mi><msup><mo lspace="0" rspace="0" stretchy="false">)</mo><mrow><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow></msup><mi>d</mi><mo lspace="0.278em" rspace="0.278em">=</mo><msup><mi>v</mi><mi>T</mi></msup><mspace width="0"/><mi>d</mi></mrow>
</math>
</span></p>
<p>This equation means that value added directly to gross output is equal to the vertically integrated value of all final products.
This is interesting and is something I have not seen in the literature.
It is similar to <a href="https://en.wikipedia.org/wiki/Gross_domestic_product">GDP</a>, or possibly <a href="https://en.wikipedia.org/wiki/Net_domestic_product">NDP</a> depending on how depreciation is accounted for in <math>
<mi>A</mi>
</math>.</p>
<p>2023-08-23 update: Ian Wright produces this same equality in his paper <a href="https://ianwrightsite.files.wordpress.com/2017/04/general-theory-labour-value2.pdf">The general theory of labour value</a> from April 2017 (fetched 2023-08-22).
Wright decomposes <math>
<mi>d</mi>
</math> (which he calls <math>
<mi>n</mi>
</math> for <em>net product</em>) into one part <math>
<mi>w</mi>
</math> consumed by workers and a second part <math>
<mi>c</mi>
</math> consumed by capitalists.
The equality is (annoyingly) stated using row vectors as <math>
<mrow><mi>l</mi><mspace width="0"/><msup><mi>q</mi><mi>T</mi></msup><mo lspace="0.278em" rspace="0.278em">=</mo><mi>v</mi><mspace width="0"/><msup><mi>n</mi><mi>T</mi></msup></mrow>
</math>.
In linear algebra literature column vectors are the norm.
End of update.</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msup><mi>l</mi><mi>T</mi></msup><mspace width="0"/><mi>d</mi></mrow>
</math>
</span></p>
<p>Finally we have this, the scalar product of value added with the mass of final goods.
I'm not sure what this is useful for but hey, it exists.</p>
<p>Both the ratio <math>
<mrow><msup><mi>v</mi><mi>T</mi></msup><mspace width="0"/><mi>d</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><msup><mi>v</mi><mi>T</mi></msup><mspace width="0"/><mi>x</mi></mrow>
</math> and <math>
<mrow><msup><mi>l</mi><mi>T</mi></msup><mspace width="0"/><mi>d</mi><mo lspace="0" rspace="0" stretchy="false">/</mo><msup><mi>v</mi><mi>T</mi></msup><mspace width="0"/><mi>x</mi></mrow>
</math> should be negatively correlated with the organic composition of capital.</p>BOINC and a Raspberry Pi CPU usage LED2022-01-12T00:20:16+01:002022-01-12T00:20:16+01:00tomastag:www.härdin.se,2022-01-12:/blog/2022/01/12/boinc-and-a-raspberry-pi-cpu-usage-led/<p>Lately I've been wanting better ways of burning electricity in my house to keep the basement above freezing in winter.
The cost of electricity isn't high enough to justify investing in a heat pump,
but I want to do something better with the electricity than just turning it into heat …</p><p>Lately I've been wanting better ways of burning electricity in my house to keep the basement above freezing in winter.
The cost of electricity isn't high enough to justify investing in a heat pump,
but I want to do something better with the electricity than just turning it into heat.
Enter <a href="https://boinc.berkeley.edu/">BOINC</a>.</p>
<p>BOINC is a platform for distributing <a href="https://en.wikipedia.org/wiki/Embarrassingly_parallel">embarassingly parallel</a> scientific computations.
I already have a machine in the kitchen handling a webcam, and I have it contributing to <a href="https://www.primegrid.com/">PrimeGrid</a> via BOINC.
But I also have some <a href="https://www.raspberrypi.org/">Raspberry Pi's</a> sitting around doing nothing.
The Pi isn't supported by PrimeGrid.
Instead I have chosen <a href="https://www.worldcommunitygrid.org/">World Community Grid</a>, mostly because of its low bandwidth usage.</p>
<p>To be able to tell whether a Pi is actually performing computations without attaching a display to it, a CPU usage indicator LED is useful.
Pin 18 on the GPIO header can be used for this.
I built some small LED modules using 2-pin socket headers, 1 kΩ resistors and red LEDs that connect nicely between pins 18 and 20 on the header.
A small python script drives the LED on each Pi.</p>
<h2>Setup</h2>
<p>First you need psutil for python which can be installed by issuing the command <code>sudo apt install python-psutil</code>.
Next you want to paste the following code into a file called <code>cpuled.py</code>. Save it to your home directory.</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">psutil</span>
<span class="kn">import</span> <span class="nn">RPi.GPIO</span> <span class="k">as</span> <span class="nn">IO</span>
<span class="n">led</span> <span class="o">=</span> <span class="mi">18</span>
<span class="n">IO</span><span class="o">.</span><span class="n">setwarnings</span><span class="p">(</span><span class="kc">False</span><span class="p">)</span>
<span class="n">IO</span><span class="o">.</span><span class="n">setmode</span><span class="p">(</span><span class="n">IO</span><span class="o">.</span><span class="n">BOARD</span><span class="p">)</span>
<span class="n">IO</span><span class="o">.</span><span class="n">setup</span><span class="p">(</span><span class="n">led</span><span class="p">,</span> <span class="n">IO</span><span class="o">.</span><span class="n">OUT</span><span class="p">)</span>
<span class="n">pwm</span> <span class="o">=</span> <span class="n">IO</span><span class="o">.</span><span class="n">PWM</span><span class="p">(</span><span class="n">led</span><span class="p">,</span> <span class="mi">100</span><span class="p">)</span>
<span class="n">pwm</span><span class="o">.</span><span class="n">start</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">psutil</span><span class="o">.</span><span class="n">cpu_percent</span><span class="p">(</span><span class="n">interval</span><span class="o">=</span><span class="mf">0.1</span><span class="p">)</span>
<span class="c1">#print(p, p*p/100)</span>
<span class="n">pwm</span><span class="o">.</span><span class="n">ChangeDutyCycle</span><span class="p">(</span><span class="n">p</span><span class="o">*</span><span class="n">p</span><span class="o">/</span><span class="mi">100</span><span class="p">)</span>
</code></pre></div>
<p>The p*p/100 is to compensate for the eye's non-linear response to light intensity. It's crude, but it works.
To get the script to start when the Raspberry Pi boots, edit the <em>pi</em> user's crontab with <code>crontab -e</code> and add the following line to the end of it:</p>
<div class="highlight"><pre><span></span><code><span class="nv">@reboot</span><span class="w"> </span><span class="n">nohup</span><span class="w"> </span><span class="n">python</span><span class="w"> </span><span class="n">cpuled</span><span class="p">.</span><span class="n">py</span>
</code></pre></div>
<p>Connect a LED and a resistor between pins 18 and 20, reboot the Pi and the LED should indicate its CPU usage.
It should look something like the following GIF, which shows a Pi 3 and a Pi 4 on top of each other, each with one LED pulsing:</p>
<p><img alt="Two Raspberry Pi's with a CPU usage LED each" src="http://www.härdin.se/images/cpuleds.gif"></p>
<p>Both Pi's are contributing to the World Community Grid.
Specifically they are running calculations relating to the COVID-19 pandemic.
From the pulsing it's possible to tell that the computations don't make the best use of each CPU.
They're sitting idle around 25% of the time.</p>
<h2>Closing remarks</h2>
<p>(Un)fortunately even the Pi 4 uses only about 5 W of power, so getting larger amounts of heat requires quite a few of them.
December and January typically needs 500 kWh of heat per month, or 700 W.
Obviously I'm not going to buy hundreds of Pi's to generate that.
What's more likely is running old-ish computers from the university.</p>Equations are now MathML2021-12-27T20:45:11+01:002021-12-27T20:45:11+01:00tomastag:www.härdin.se,2021-12-27:/blog/2021/12/27/equations-are-now-mathml/<p>Today I switched to <a href="http://gva.noekeon.org/blahtexml/">blahtexml</a> and <a href="https://en.wikipedia.org/wiki/MathML">MathML</a> for the LaTeX equations on here.
Before this equations were implemented via SVG files rendered by <a href="https://github.com/justinvh/Markdown-LaTeX">Markdown-LaTeX</a>.
The generated SVG was then inlined by base64 encoding.
To get the rendering right, fonts had to be embedded into each base64'd SVG file.
This meant …</p><p>Today I switched to <a href="http://gva.noekeon.org/blahtexml/">blahtexml</a> and <a href="https://en.wikipedia.org/wiki/MathML">MathML</a> for the LaTeX equations on here.
Before this equations were implemented via SVG files rendered by <a href="https://github.com/justinvh/Markdown-LaTeX">Markdown-LaTeX</a>.
The generated SVG was then inlined by base64 encoding.
To get the rendering right, fonts had to be embedded into each base64'd SVG file.
This meant a lot more data than necessary had to be transmitted in the HTML, as much as 184 KiB after compression.
Generating the website from scratch also took a long time, on the order of minutes.</p>
<p>blahtexml on the other hand can transform LaTeX into MathML, and is available in Debian.
Because MathML is used, the HTML shrinks massively and generation is much much faster.
Another bonus is that the website is more accessible to people with impaired vision.</p>
<p>For fun I have tabled the HTML size differences of relevant articles below, after compression:</p>
<table>
<tr><th>Article</th><th>Before (KiB)</th><th>After (KiB)</th></tr>
<tr><td><a href="http://www.härdin.se/blog/2021/02/24/planning-complexity-for-model-economies/">Planning complexity for model economies</a></td><td>183.93</td><td>9.44</td></tr>
<tr><td><a href="http://www.härdin.se/blog/2021/02/08/some-example-economic-linear-programs/">Some example economic linear programs</a></td><td>105.07</td><td>6.96</td></tr>
<tr><td><a href="http://www.härdin.se/blog/2021/05/01/verifiable-sortition/">Verifiable sortition</a></td><td>38.45</td><td>5.18</td></tr>
<tr><td><a href="http://www.härdin.se/blog/2021/03/04/reducing-emissions-and-saving-lives/">Reducing emissions and saving lives</a></td><td>14.21</td><td>5.15</td></tr>
<tr><td><a href="http://www.härdin.se/blog/2021/11/17/prices-and-information-part-2/">Prices and information part 2</a></td><td>10.20</td><td>4.12</td></tr>
</table>Mixed integer planning2021-12-08T23:20:00+02:002021-12-08T23:20:00+02:00tomastag:www.härdin.se,2021-12-08:/blog/2021/12/08/mixed-integer-planning/<p>In the first post in this series I made the point that while linear programming gets us quite far in planning,
it cannot deal with the non-linearities which exist in real economies.
In order to get a feeling for how difficult this actually is, I've been dipping my toes into …</p><p>In the first post in this series I made the point that while linear programming gets us quite far in planning,
it cannot deal with the non-linearities which exist in real economies.
In order to get a feeling for how difficult this actually is, I've been dipping my toes into <a href="https://en.wikipedia.org/wiki/Integer_programming">mixed integer programming</a> (MIP).</p>
<p>A program in MIP is like a normal linear program with the additional constraint that some variables must be integral.
This pops up whenever we can't make fractional amounts of something.
For example it makes no sense to build half a car.
Many combinatorial optimization problems can be formulated as MIPs,
like the <a href="https://en.wikipedia.org/wiki/Knapsack_problem">knapsack problem</a>
and the <a href="https://en.wikipedia.org/wiki/Travelling_salesman_problem">travelling salesman problem</a>.
A problem that is very relevant to planning is the <a href="https://en.wikipedia.org/wiki/Facility_location_problem">facility location problem</a>,
which covers things like when and where to build new production facilities.</p>
<p>I will be using the computer game <a href="https://www.sovietrepublic.net/">Workers & Resources: Soviet Republic</a> as a model economy to illustrate this post.
I have written a program that parses the data files in the game,
which I plan on writing about in a separate post.</p>
<h2>When MIP is useful</h2>
<p>MIP is useful whenever we need to plan when and where to make capital investments.
Setting up a cement plant must be done in full before it can be brought into use.
If one plant can make 2.7 tons of cement per hour then two plants can make 5.4,
but 1½ plants can still only make 2.7.
Two incomplete plants can obviously make zero cement.
For simplicity I assume that plants are constructed sequentially.
The following mixed integer program illustrates the concept:</p>
<div class="highlight"><pre><span></span><code><span class="n">max</span><span class="o">:</span><span class="w"> </span><span class="n">cement</span><span class="o">;</span>
<span class="c1">// resources on hand</span>
<span class="n">concrete</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1500</span><span class="o">;</span>
<span class="n">gravel</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">150</span><span class="o">;</span>
<span class="n">cement</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">2.7</span><span class="w"> </span><span class="n">plants</span><span class="o">;</span>
<span class="mi">739</span><span class="w"> </span><span class="n">plants</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">concrete</span><span class="o">;</span>
<span class="mi">70</span><span class="w"> </span><span class="n">plants</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">gravel</span><span class="o">;</span>
<span class="n">int</span><span class="w"> </span><span class="n">plants</span><span class="o">;</span>
</code></pre></div>
<p>Feed this into <code>lp_solve</code> and it will spit out the solution <em>plants = 2</em>, <em>cement = 5.4</em>.
But if concrete is decreased only slightly to 1400 then the optimal solution is <em>plants = 1</em>, <em>cement = 2.7</em>.
Remove the integer constraint while keeping <em>concrete = 1400</em> and the solution becomes <em>plants = 1.89445</em>, <em>cement = 5.11502</em>.</p>
<p>But this example is boring. We have no notion of time. Let's add one.</p>
<h2>Discretized time</h2>
<p>One way to introduce time into a MIP is through discretization.
This can be monotonic for all variables in some given time interval,
or we can use a non-monotonic grid, or even a separate non-monotonic grid for each variable.
Let's use the same monotonic grid for all variables for simplicity.</p>
<p>The value of each variable at time <em>t</em> depends on their values and the plan at time <em>t - 1</em>.
<em>Plan</em> here means the activation level of each plant.
In Workers & Resources this means how many workers should work at each workplace in each planning period.
We typically don't want workers doing jobs that are unnecessary at the moment.
In real life this could mean purposefully giving people time off.</p>
<p>The following MIP covers three planning periods/four time instants on a monotonic grid:</p>
<div class="highlight"><pre><span></span><code><span class="n">max</span><span class="o">:</span><span class="w"> </span><span class="n">cement_3</span><span class="o">;</span>
<span class="c1">// initial resources</span>
<span class="n">cement_0</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="o">;</span>
<span class="n">concrete_0</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1500</span><span class="o">;</span>
<span class="n">gravel_0</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">200</span><span class="o">;</span>
<span class="n">coal_0</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">10</span><span class="o">;</span>
<span class="c1">// size of the working population</span>
<span class="n">workers</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">6000</span><span class="o">;</span>
<span class="c1">// initial plants</span>
<span class="n">plants_0</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="o">;</span>
<span class="c1">// 0 -> 1</span>
<span class="n">workers_cement_0</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="mi">30</span><span class="w"> </span><span class="n">plants_0</span><span class="o">;</span>
<span class="n">cement_prod_0</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.09</span><span class="w"> </span><span class="n">workers_cement_0</span><span class="o">;</span>
<span class="n">coal_cement_0</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.025</span><span class="w"> </span><span class="n">workers_cement_0</span><span class="o">;</span>
<span class="n">gravel_cement_0</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.233</span><span class="w"> </span><span class="n">workers_cement_0</span><span class="o">;</span>
<span class="mi">5676</span><span class="w"> </span><span class="n">new_plants_0</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">workers_construct_0</span><span class="o">;</span>
<span class="mi">739</span><span class="w"> </span><span class="n">new_plants_0</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">concrete_construct_0</span><span class="o">;</span>
<span class="mi">70</span><span class="w"> </span><span class="n">new_plants_0</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">gravel_construct_0</span><span class="o">;</span>
<span class="n">workers_cement_0</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">workers_construct_0</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">workers</span><span class="o">;</span>
<span class="n">plants_1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">plants_0</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">new_plants_0</span><span class="o">;</span>
<span class="n">cement_1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cement_0</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">cement_prod_0</span><span class="o">;</span>
<span class="n">coal_1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">coal_0</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">coal_cement_0</span><span class="o">;</span>
<span class="n">gravel_1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">gravel_0</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">gravel_cement_0</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">gravel_construct_0</span><span class="o">;</span>
<span class="n">concrete_1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">concrete_0</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">concrete_construct_0</span><span class="o">;</span>
<span class="c1">// 1 -> 2</span>
<span class="n">workers_cement_1</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="mi">30</span><span class="w"> </span><span class="n">plants_1</span><span class="o">;</span>
<span class="n">cement_prod_1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.09</span><span class="w"> </span><span class="n">workers_cement_1</span><span class="o">;</span>
<span class="n">coal_cement_1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.025</span><span class="w"> </span><span class="n">workers_cement_1</span><span class="o">;</span>
<span class="n">gravel_cement_1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.233</span><span class="w"> </span><span class="n">workers_cement_1</span><span class="o">;</span>
<span class="mi">5676</span><span class="w"> </span><span class="n">new_plants_1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">workers_construct_1</span><span class="o">;</span>
<span class="mi">739</span><span class="w"> </span><span class="n">new_plants_1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">concrete_construct_1</span><span class="o">;</span>
<span class="mi">70</span><span class="w"> </span><span class="n">new_plants_1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">gravel_construct_1</span><span class="o">;</span>
<span class="n">workers_cement_1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">workers_construct_1</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">workers</span><span class="o">;</span>
<span class="n">plants_2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">plants_1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">new_plants_1</span><span class="o">;</span>
<span class="n">cement_2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cement_1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">cement_prod_1</span><span class="o">;</span>
<span class="n">coal_2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">coal_1</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">coal_cement_1</span><span class="o">;</span>
<span class="n">gravel_2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">gravel_1</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">gravel_cement_1</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">gravel_construct_1</span><span class="o">;</span>
<span class="n">concrete_2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">concrete_1</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">concrete_construct_1</span><span class="o">;</span>
<span class="c1">// 2 -> 3</span>
<span class="n">workers_cement_2</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="mi">30</span><span class="w"> </span><span class="n">plants_2</span><span class="o">;</span>
<span class="n">cement_prod_2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.09</span><span class="w"> </span><span class="n">workers_cement_2</span><span class="o">;</span>
<span class="n">coal_cement_2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.025</span><span class="w"> </span><span class="n">workers_cement_2</span><span class="o">;</span>
<span class="n">gravel_cement_2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.233</span><span class="w"> </span><span class="n">workers_cement_2</span><span class="o">;</span>
<span class="n">cement_3</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cement_2</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">cement_prod_2</span><span class="o">;</span>
<span class="n">coal_3</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">coal_2</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">coal_cement_2</span><span class="o">;</span>
<span class="n">gravel_3</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">gravel_2</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">gravel_cement_2</span><span class="o">;</span>
<span class="n">int</span><span class="w"> </span><span class="n">new_plants_0</span><span class="o">;</span>
<span class="n">int</span><span class="w"> </span><span class="n">new_plants_1</span><span class="o">;</span>
</code></pre></div>
<p>This may look intimidating, but the three bigger blocks of equations are mostly copies of each other.
The last block is simplified.
Let's look at the first block more closely:</p>
<div class="highlight"><pre><span></span><code>workers_cement_0 <= 30 plants_0;
cement_prod_0 = 0.09 workers_cement_0;
coal_cement_0 = 0.025 workers_cement_0;
gravel_cement_0 = 0.233 workers_cement_0;
</code></pre></div>
<p>This part covers production in the cement plants.
Each plant can employ up to 30 workers,
and each worker produces 0.09 tons of cement per hour given 0.025 tons of coal and 0.233 tons of gravel.</p>
<div class="highlight"><pre><span></span><code><span class="mf">5676</span><span class="w"> </span><span class="kr">new</span><span class="n">_plants_0</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">workers_construct_0</span><span class="p">;</span>
<span class="mf">739</span><span class="w"> </span><span class="kr">new</span><span class="n">_plants_0</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">concrete_construct_0</span><span class="p">;</span>
<span class="mf">70</span><span class="w"> </span><span class="kr">new</span><span class="n">_plants_0</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">gravel_construct_0</span><span class="p">;</span>
</code></pre></div>
<p>This part covers the construction of new plants.
It is similar to what we had in the previous section, except with an added constraint for construction workers.
For simplicity each plant is built fully within one planning period (one hour!)</p>
<div class="highlight"><pre><span></span><code><span class="n">workers_cement_0</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">workers_construct_0</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">workers</span><span class="p">;</span>
</code></pre></div>
<p>This limits where workers may be employed - either in construction or cement production.</p>
<div class="highlight"><pre><span></span><code><span class="n">plants_1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">plants_0</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">new_plants_0</span><span class="p">;</span>
<span class="n">cement_1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cement_0</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">cement_prod_0</span><span class="p">;</span>
<span class="n">coal_1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">coal_0</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">coal_cement_0</span><span class="p">;</span>
<span class="n">gravel_1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">gravel_0</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">gravel_cement_0</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">gravel_construct_0</span><span class="p">;</span>
<span class="n">concrete_1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">concrete_0</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">concrete_construct_0</span><span class="p">;</span>
</code></pre></div>
<p>This describes how the different means of production change from one time instant to the next.
The solution looks like this, after sorting the variables so we can see how they change over time:</p>
<div class="highlight"><pre><span></span><code><span class="n">Value</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">objective</span><span class="w"> </span><span class="n">function</span><span class="p">:</span><span class="w"> </span><span class="mf">8.10000000</span>
<span class="n">cement_0</span><span class="w"> </span><span class="mi">0</span>
<span class="n">cement_1</span><span class="w"> </span><span class="mi">0</span>
<span class="n">cement_2</span><span class="w"> </span><span class="mf">2.7</span>
<span class="n">cement_3</span><span class="w"> </span><span class="mf">8.1</span>
<span class="n">cement_prod_0</span><span class="w"> </span><span class="mi">0</span>
<span class="n">cement_prod_1</span><span class="w"> </span><span class="mf">2.7</span>
<span class="n">cement_prod_2</span><span class="w"> </span><span class="mf">5.4</span>
<span class="n">coal_0</span><span class="w"> </span><span class="mi">10</span>
<span class="n">coal_1</span><span class="w"> </span><span class="mi">10</span>
<span class="n">coal_2</span><span class="w"> </span><span class="mf">9.25</span>
<span class="n">coal_3</span><span class="w"> </span><span class="mf">7.75</span>
<span class="n">coal_cement_0</span><span class="w"> </span><span class="mi">0</span>
<span class="n">coal_cement_1</span><span class="w"> </span><span class="mf">0.75</span>
<span class="n">coal_cement_2</span><span class="w"> </span><span class="mf">1.5</span>
<span class="n">concrete_0</span><span class="w"> </span><span class="mi">1500</span>
<span class="n">concrete_1</span><span class="w"> </span><span class="mi">761</span>
<span class="n">concrete_2</span><span class="w"> </span><span class="mi">22</span>
<span class="n">concrete_construct_0</span><span class="w"> </span><span class="mi">739</span>
<span class="n">concrete_construct_1</span><span class="w"> </span><span class="mi">739</span>
<span class="n">gravel_0</span><span class="w"> </span><span class="mi">200</span>
<span class="n">gravel_1</span><span class="w"> </span><span class="mi">130</span>
<span class="n">gravel_2</span><span class="w"> </span><span class="mf">53.01</span>
<span class="n">gravel_3</span><span class="w"> </span><span class="mf">39.03</span>
<span class="n">gravel_cement_0</span><span class="w"> </span><span class="mi">0</span>
<span class="n">gravel_cement_1</span><span class="w"> </span><span class="mf">6.99</span>
<span class="n">gravel_cement_2</span><span class="w"> </span><span class="mf">13.98</span>
<span class="n">gravel_construct_0</span><span class="w"> </span><span class="mi">70</span>
<span class="n">gravel_construct_1</span><span class="w"> </span><span class="mi">70</span>
<span class="n">new_plants_0</span><span class="w"> </span><span class="mi">1</span>
<span class="n">new_plants_1</span><span class="w"> </span><span class="mi">1</span>
<span class="n">plants_0</span><span class="w"> </span><span class="mi">0</span>
<span class="n">plants_1</span><span class="w"> </span><span class="mi">1</span>
<span class="n">plants_2</span><span class="w"> </span><span class="mi">2</span>
<span class="n">workers</span><span class="w"> </span><span class="mi">6000</span>
<span class="n">workers_cement_0</span><span class="w"> </span><span class="mi">0</span>
<span class="n">workers_cement_1</span><span class="w"> </span><span class="mi">30</span>
<span class="n">workers_cement_2</span><span class="w"> </span><span class="mi">60</span>
<span class="n">workers_construct_0</span><span class="w"> </span><span class="mi">5676</span>
<span class="n">workers_construct_1</span><span class="w"> </span><span class="mi">5676</span>
</code></pre></div>
<p>Since we're maximizing cement production we see the amount of cement rising over time.
Gravel is spent both on construction and in cement production.
I encourage you, dear reader, to experiment a bit with this program by answering the following questions.</p>
<ul>
<li>What happens if coal_0 is limited to 2 tons? 1 ton?</li>
<li>What happens if gravel_0 is limited to 150?</li>
<li>What happens if the number of workers is doubled? Limited to 5676? 5675?</li>
<li>What happens if plants_0 is set to 1?</li>
</ul>
<p>The following python3 script generalizes the MIP given above to any number of periods:</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">sys</span>
<span class="n">n</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"""max: cement_</span><span class="si">{</span><span class="n">n</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2">;</span>
<span class="s2">// initial resources</span>
<span class="s2">cement_000000 = 0;</span>
<span class="s2">concrete_000000 = 1500;</span>
<span class="s2">gravel_000000 = 200;</span>
<span class="s2">coal_000000 = 10;</span>
<span class="s2">// size of the working population</span>
<span class="s2">workers = 6000;</span>
<span class="s2">// initial plants</span>
<span class="s2">plants_000000 = 0;"""</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"""// </span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> -> </span><span class="si">{</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span>
<span class="s2">workers_cement_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> <= 30 plants_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2">;</span>
<span class="s2">cement_prod_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> = 0.09 workers_cement_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2">;</span>
<span class="s2">coal_cement_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> = 0.025 workers_cement_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2">;</span>
<span class="s2">gravel_cement_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> = 0.233 workers_cement_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2">;</span>
<span class="s2">5676 new_plants_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> = workers_construct_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2">;</span>
<span class="s2">739 new_plants_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> = concrete_construct_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2">;</span>
<span class="s2">70 new_plants_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> = gravel_construct_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2">;</span>
<span class="s2">workers_cement_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> + workers_construct_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> <= workers;</span>
<span class="s2">plants_</span><span class="si">{</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> = plants_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> + new_plants_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2">;</span>
<span class="s2">cement_</span><span class="si">{</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> = cement_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> + cement_prod_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2">;</span>
<span class="s2">coal_</span><span class="si">{</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> = coal_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> - coal_cement_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2">;</span>
<span class="s2">gravel_</span><span class="si">{</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> = gravel_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> - gravel_cement_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> - gravel_construct_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2">;</span>
<span class="s2">concrete_</span><span class="si">{</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> = concrete_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> - concrete_construct_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2">;"""</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"""// </span><span class="si">{</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> -> </span><span class="si">{</span><span class="n">n</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span>
<span class="s2">workers_cement_</span><span class="si">{</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> <= 30 plants_</span><span class="si">{</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2">;</span>
<span class="s2">cement_prod_</span><span class="si">{</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> = 0.09 workers_cement_</span><span class="si">{</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2">;</span>
<span class="s2">coal_cement_</span><span class="si">{</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> = 0.025 workers_cement_</span><span class="si">{</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2">;</span>
<span class="s2">gravel_cement_</span><span class="si">{</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> = 0.233 workers_cement_</span><span class="si">{</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2">;</span>
<span class="s2">cement_</span><span class="si">{</span><span class="n">n</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> = cement_</span><span class="si">{</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> + cement_prod_</span><span class="si">{</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2">;</span>
<span class="s2">coal_</span><span class="si">{</span><span class="n">n</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> = coal_</span><span class="si">{</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> - coal_cement_</span><span class="si">{</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2">;</span>
<span class="s2">gravel_</span><span class="si">{</span><span class="n">n</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> = gravel_</span><span class="si">{</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2"> - gravel_cement_</span><span class="si">{</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2">;"""</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"int new_plants_</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2">;"</span><span class="p">)</span>
</code></pre></div>
<p>The script above takes a single positional argument for the number of plan periods.
To generate and solve a program for N periods, do the following:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>python<span class="w"> </span>generate.py<span class="w"> </span><span class="nv">$N</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>lp_solve
</code></pre></div>
<p><code>lp_solve</code> version 5.5.2.5-2 happens to solve this class of programs in O(N²) time, even when the integer constraints are removed. This doesn't demonstrate NP-hardness as I'd like. Oh well. Update: I also ran these problems through <code>glpsol</code> version 5.0-1, part of the <a href="https://www.gnu.org/software/glpk/">glpk</a> package, and it solves them in O(N) time.</p>
<p>Bringing more industries into the program listed above is left as an exercise for the reader.
The resulting class of programs is block diagonal.</p>
<h2>Non-convex planning</h2>
<p>One limitation of the scheme above is that it assumes productivity is entirely linear, or possibly "lumpy" if capital investments are to be optimized.
There is no way of dealing with economics of scale, which is a major weakness of Kantorovich's proposal to use linear programming for planning.
More recently the weakness of LP for planning has been pointed in the 2012 blog post <a href="https://crookedtimber.org/2012/05/30/in-soviet-union-optimization-problem-solves-you/">In Soviet Union, Optimization Problem Solves <em>You</em></a> by Cosma Shalizi.</p>
<p>Finding optimal solutions to non-convex programs is in general NP-hard.
We know that finding approximate solutions to linear programs is P, and that a solution that is within 1% of optimum is likely good enough for planning.
For any non-convex program with a non-empty feasible region we can inscribe a linear program which in turn can be solved approximately in P.
The following figure illustrates the concept:</p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/mixed_integer_planning/program-inscribe.svg" alt="Non-convex program with linear program inscribed"/></p>
<p>We are minimizing labour.
The non-convex program <em>P</em> has a global optimum <em>x*</em>.
Imagine that we initially find an inscribed linear program <em>P<sub>1</sub></em> through some process.
It has the optimal solution <em>x<sub>1</sub></em>, an approximation of which we can find quickly.
We can imagine that we then find a new inscribed linear program <em>P<sub>2</sub></em> by using <em>x<sub>1</sub></em> as a hint.</p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/mixed_integer_planning/program-inscribe-2.svg" alt="New linear program inscribed, near a local minium"/></p>
<p>Clearly this process would eventually lead to the local optimum <em>x<sub>L</sub></em> after some time.
And this is not dissimilar to how capitalism tends to find local optima.
But we can apply ideas from non-linear optimization to get out of local optima,
for example simulated annealing or random restart.
We can use different inscribed linear programs - there are an infinite number of them to choose from.</p>
<p>But how does this apply to planning?</p>
<h2>Piecewise linearization</h2>
<p>In MIP there is something called <a href="https://en.wikipedia.org/wiki/Special_ordered_set">special ordered sets</a> that can be used to solve non-convex programs via piecewise linearization.
<code>lp_solve</code> can do this via the <a href="http://lpsolve.sourceforge.net/5.5/SOS.htm">SOS command</a>.
For these linearizations we can also find linear functions that result in inscribed linear programs as discussed in the previous section.
We can use the current feasible solution to "tighten" the inscribed linear program by bringing these linear functions closer to the linearizations. The following figure illustrates the idea:</p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/mixed_integer_planning/sos2.svg" alt="SOS2 example"/></p>
<p><em>s</em> is the amount of something to make and <em>f</em> is how much of some resource is necessary.
The figure illustrates economics of scale - as <em>s</em> increases, the marginal demand for <em>f</em> goes down (<em>d²f/ds² < 0</em>).
At each iteration we have some <em>s<sup>(i)</sup></em> that we can use to choose the linearization, so long as it doesn't underestimate <em>f</em>.
We can also add bounds to <em>s</em> so that we can be more aggresive with our choice of linearization.
This is useful if d²f/ds² changes sign, like below:</p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/mixed_integer_planning/sos2-2.svg" alt="SOS2 example with S-shaped curve"/></p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/mixed_integer_planning/sos2-2-bounds.svg" alt="The previous example, with bounds"/></p>
<p>Here the linearization of <em>f</em> is valid for <em>s<sub>L</sub> ≤ s ≤ s<sub>U</sub></em>.</p>
<h2>Continuous functions</h2>
<p>So far we've only looked at piecewise linearizations.
The reason for this is because we can solve these exactly using any MIP solver.
Another reason is that we can ask people at each workplace how much stuff they think they need to effect large changes in output.
"How much do you need now? How much to make twice as much? Half as much?".
Such questions, if they can be answered, are discrete points.
An obvious choice for interpolation is a piecewise linear function.
But we can just as well choose some continuous function, and the linearization strategy works just as well!</p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/mixed_integer_planning/sos2-continuous.svg" alt="Continuous example"/></p>
<p>But, most of the time it might not be possible for people to answer questions about large-scale changes in production.
The only things we know for certain are historical values for <em>s</em> and <em>f</em>.
If we're lucky we might get a decent estimate for <em>df/ds</em>, the answer to the question "how much more/less do you need to change output by a small amount?"
This looks something like the following:</p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/mixed_integer_planning/historical.svg" alt="Example with historical value and local derivative"/></p>
<p>I owe this notion to a recent discussion with <a href="http://ssamot.me/">Spyridon Samothrakis</a> and Dave Zachariah.
So a better view of the situation might be something like this:</p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/mixed_integer_planning/program-unknown.svg" alt="An 'ethereal' non-convex program with a linear program inscribed"/></p>
<p>The linear program is smaller because we're less sure what the functions that make up our constraints even are.
I therefore call the uncertain program that we're trying to solve <em>P<sub>?</sub></em>.</p>
<h2>Conclusions</h2>
<p>One feature of the formalization discussed here is that it improves on "Leontief-y" proposals for non-convex planning.
By Leontief here I mean square systems based on IO tables.
It turns out we need rectangular systems in planning or else we can't weigh multiple methods of achieving the same goal.
IO tables cannot help us choose between burning anthracite, wood or uranium when generating electricity.</p>
<p>The uncertainties in the functions that make up our constraints imply limits on the optimizations we can actually implement.
We can only move close to constraints which we are certain are not optimistic.
We can account for this uncertainty in the solver by assigning appropriate "forces" to each constraint,
meaning different constants before each <em>c<sub>i</sub>(x)</em> term in the barrier function used in the solver (see <a href="https://en.wikipedia.org/wiki/Interior-point_method">interior-point methods</a>).
This will tend to push the solutions toward more certain constraints.</p>
<p>Physics can be used to verify aspects of some constraints. Thermodynamics is one example of this.
Similarly we can apply mass and energy conservation, demanding that the flow of these be accounted for.
If a sawmill is fed with logs then we expect the mass of boards, sawdust and bark that is output are no more than what has been supplied.
We also expect it to be not too much less than what is put in, minus moisture lost in drying.</p>
<p>If we violate a constraint that exists in reality but which we have failed to model then we have an infeasible plan.
Say that we only today discovered that atmospheric CO<sub>2</sub> affects the energy balance of the Earth.
Such new knowledge about reality would immediately make our current plan infeasible,
and we would have to change the plan accordingly.
The "stiffer" our plan is the harder it will likely be to reorient the economy.</p>
<p>I suspect that the most important short-term goal may not be optimality but feasibility.
We can only do things like reduce working hours if we are certain nothing will break from doing so.
We certainly need to bring the amount of greenhouse gasses in the atmosphere into regulation before we can hope to optimize on labour.</p>
<p>That's it for this post.
As always, if you like these posts then I recommend subscribing via RSS/Atom using either of the links below.
You can use a news reader like <a href="https://quiterss.org/en">QuiteRSS</a> to do so.</p>Kildemoes City Shopping teardown2021-12-05T16:01:16+02:002021-12-05T16:01:16+02:00tomastag:www.härdin.se,2021-12-05:/blog/2021/12/05/kildemoes-city-shopping-teardown/<p><a href="http://www.härdin.se/images/kildemoes_teardown/PC052257.JPG"><img alt="Photo of the bike, battery missing" src="http://www.härdin.se/images/kildemoes_teardown/tPC052257.JPG"></a></p>
<p>The battery for my electric bike was recently stolen.
To try and save some money I've been looking at building a replacement battery from some 18650 cells I have laying around.
As part of this I thought I should document my findings on the blog.
Hopefully it helps someone.
The …</p><p><a href="http://www.härdin.se/images/kildemoes_teardown/PC052257.JPG"><img alt="Photo of the bike, battery missing" src="http://www.härdin.se/images/kildemoes_teardown/tPC052257.JPG"></a></p>
<p>The battery for my electric bike was recently stolen.
To try and save some money I've been looking at building a replacement battery from some 18650 cells I have laying around.
As part of this I thought I should document my findings on the blog.
Hopefully it helps someone.
The bike is a Kildemoes City Shopping with an Egoing system.</p>
<p>Note that versions of this post from before 2021-12-21 have VDD on the wrong battery pin.
I have also changed the pin order and names to match Phylion's documentation.
If you have information from the old version written down/stored then please update it.</p>
<p>Tools needed:</p>
<ul>
<li>3 mm hex driver</li>
<li>5 mm hex driver</li>
<li>PH1 driver</li>
<li>PH2 driver</li>
</ul>
<h2>Front</h2>
<p>The front has the display unit, the motor and a 2.5W LED.
The display unit has a USB outlet and three buttonss:</p>
<ul>
<li>an on/off button marked ⏻</li>
<li>a button marked + for increasing power and turning the LED on/off (if held down for a few seconds)</li>
<li>a button marked - for decreasing power and turning on a "walk mode" which runs the motor at around 5 km/h without having to pedal</li>
</ul>
<p>The walk mode may technically be illegal under Swedish law unless the bike is considered a "transportation aid" in this mode.
It amounts to a throttle, which is not legal to have on a bike.
Curiously throttles are legal on vehicles that go no faster than 25 km/h with motor power below 250W <em>if they have no pedals</em>.
Perhaps this technicality is useful to someone.
Disability aids are allowed any amount of power, and throttles, but are still limited to 25 km/h.</p>
<p>There are seven LEDs on the display.
Four LEDs show the amount of energy left in the battery.
The remaining three LEDs show the motor power mode.
These LEDs can also indicate errors, the meaning of which can be looked up in the manual.</p>
<p>The display is held to the steering bar with a 3 mm hex screw.
The hex screw "strap unit" is held to the display with four small PH1 screws.
The display unit itself seems to be held together with two PH1 or PH2 screws buried under rubber.
Removing the rubber and unscrewing them as far as possible unfortunately does not enable taking the unit apart.
It is also not possible to bend the unit apart, at least with the modest amount of force I was willing to use.</p>
<h2>Rear</h2>
<p><a href="http://www.härdin.se/images/kildemoes_teardown/PC032242.JPG"><img alt="Bottom of luggage carrier" src="http://www.härdin.se/images/kildemoes_teardown/tPC032242.JPG"></a></p>
<p>The rear of the bike has a luggage carrier which contains the battery and the ESC.
The battery holder and ESC are both part of one plastic unit which I will call the control box.
The control box can be removed by unscrewing the four 5 mm hex screws underneath the luggage carrier.
To access these screws you need to first remove the luggage carrier, which is also held on with four 5 mm hex screws.
Be careful not to mix the screws up, since they all have different lengths.
When you remove the control box a 20mm diameter knurled thing will also come loose. I am not sure of the function of this piece.</p>
<p><a href="http://www.härdin.se/images/kildemoes_teardown/PC032243.JPG"><img alt="Knurled object" src="http://www.härdin.se/images/kildemoes_teardown/tPC032243.JPG"></a></p>
<p>There are six pins sticking out of the control box. These pins connect to the battery.
The leftmost pair of pins are marked "+" and the rightmost pins are marked "-".
These correspond to the rightmost and leftpost connectors on the battery.
On the floor of the control box, underneath where the battery normally sits, there are some markings.
The text "MJXH003" is molded into the plastic and "SWXK Motor" is laser engraved.
Between these two markings there is a paper label with the following text:</p>
<p><a href="http://www.härdin.se/images/kildemoes_teardown/PC032247.JPG"><img alt="Label" src="http://www.härdin.se/images/kildemoes_teardown/tPC032247.JPG"></a></p>
<div class="highlight"><pre><span></span><code><span class="n">Controller</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">brushless</span><span class="w"> </span><span class="n">motor</span>
<span class="n">Rated</span><span class="w"> </span><span class="nl">voltage</span><span class="p">:</span><span class="w"> </span><span class="mi">37</span><span class="n">V</span>
<span class="n">Maximum</span><span class="w"> </span><span class="k">current</span><span class="err">:</span><span class="w"> </span><span class="mi">12</span><span class="n">A</span>
<span class="n">Rated</span><span class="w"> </span><span class="k">current</span><span class="err">:</span><span class="w"> </span><span class="mi">6</span><span class="n">A</span>
<span class="n">Low</span><span class="w"> </span><span class="n">voltage</span><span class="w"> </span><span class="nl">protection</span><span class="p">:</span><span class="w"> </span><span class="mi">31</span><span class="n">V</span>
<span class="n">Product</span><span class="w"> </span><span class="nl">number</span><span class="p">:</span><span class="w"> </span><span class="n">LSW936</span><span class="o">-</span><span class="mi">8</span>
<span class="nl">Model</span><span class="p">:</span><span class="w"> </span><span class="n">C8705017</span><span class="o">-</span><span class="mi">04</span><span class="o">-</span><span class="mi">28</span><span class="n">BK</span>
<span class="n">Ex</span><span class="o">-</span><span class="n">factory</span><span class="w"> </span><span class="nc">date</span><span class="err">:</span><span class="w"> </span><span class="mi">12</span><span class="w"> </span><span class="mi">2014</span>
<span class="n">EN</span><span class="w"> </span><span class="mi">15194</span>
<span class="n">CE</span><span class="w"> </span><span class="o">[</span><span class="n">logos</span><span class="o">]</span>
</code></pre></div>
<p>While the controller is rated for 37 V, it will accept at least up to 42 V.
The quiescent current is 58 mA in my tests and does not seem to depend on the battery voltage.
Turning on the light increases current draw to 125 mA at 42 V, 135 mA at 36 V.
An error LED will blink if the controller is supplied from a power supply rather than a legitimate battery, meaning the four other pins have some function on this particular controller. More on this later.</p>
<p>The control box is held together with four PH1 screws. Unscrew them and the ESC falls out.</p>
<p><a href="http://www.härdin.se/images/kildemoes_teardown/PC032250.JPG"><img alt="ESC in plastic holder" src="http://www.härdin.se/images/kildemoes_teardown/tPC032250.JPG"></a></p>
<p>With the ESC oriented so that the text on the label can be read, and the pins sticking up, there is what appears to be a programming connector on the right, attached by a white cable.
It has a silicone weather protection cap.
On the right there is a box into which four wires enter on one side and two wires on the other. It is marked 6V followed by some chinese writing that I do not understand.
Possibly this is a 6V buck converter. If so then I expect a 5V LDO on the board.
There are seven TO-220 packages, so it is likely one of them is this LDO and the rest are MOSFETs for driving the motor.
The ESC is held in place with two PH2 screws.</p>
<p>Looking on the back of the battery connector, it turns out that it is the leftmost pin that is positive supply and the rightmost pin that is negative, because + and - are molded into the plastic directly behind them, something that is not mechanically possible to do on the front of the connector.
The board is conformally coated.
The chips on the board have no visible markings.
On the leftmost side of the board is what appears to be a current shunt, connected with a thick trace to the negative pin.</p>
<p><a href="http://www.härdin.se/images/kildemoes_teardown/PC032253.JPG"><img alt="Close-up of board" src="http://www.härdin.se/images/kildemoes_teardown/tPC032253.JPG"></a></p>
<p>The leftmost TO-220 has no visible markings.
The presence of a through-hole bulk capacitor near the first TO-220 supports the theory that this is a regulator. The capacitor measures 1370 µF.
There is also a rather large 150 Ohm 0.5% through-hole resistor behind the bulk capacitor (brown-green-brown-[gap]-green).</p>
<p>The other six TO-220's are marked <a href="https://www.st.com/resource/en/datasheet/stp80nf70.pdf">80NF70</a>, meaning 68V N-channel MOSFETs.</p>
<p>There are two more through-hole electrolytic capacitors on the board, both 100µF 50V.</p>
<p>There are two surface-mount electrolytics marked 100µF 16V and three ones marked 10µF 50V.
Next to each of the three 10µF caps are a diode and what I suspect are MOSFET gate driver chips, three of each in total.</p>
<p>The battery is a Phylion Joycube.</p>
<h2>Pinout and protocol reverse engineering</h2>
<p>The order and names of pins here come from Phylion's documentation.
RX/TX are 5V UART at 9600 baud, one start bit, eight data bits, one stop bit.
I suspect the battery is a slave device.
Either the ESC or the display unit should be the master.</p>
<table>
<tr><th>Pin</th><th>Name</th><th>Function</th></tr>
<tr><td>1</td><td>P+</td><td>Battery positive</td></tr>
<tr><td>2</td><td>VCC</td><td>Lights (front and rear)</td></tr>
<tr><td>3</td><td>VDD</td><td>+5V (measures +4.75 V). Powers RX/TX optoisolators on battery BMS board.</td></tr>
<tr><td>4</td><td>RX</td><td>MOSI. Does not go high immediately. Active after pin 2. Marked "RX" on BMS board. Weakly driven.</td></tr>
<tr><td>5</td><td>TX</td><td>MISO. Goes high as soon as the on/off switch is pushed. Active before pin 3. Marked "TX" on BMS board, confirmed MISO via reverse engineering. 560 Ohm to VDD.</td></tr>
<tr><td>6</td><td>P-</td><td>Battery negative</td></tr>
</table>
<p>The connector in front of the control box has 13 pins.
Three of these pins go to the motor and measure 0.5 Ohm between each pair.
The remaining 10 pins go to the display.
Of the 10 display pins, 7 connect to the battery pins.
Looking at the pin side of the connector, I will be using the following labelling system:</p>
<p><img style="display:block;width:40%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/kildemoes_teardown/13pin.svg" alt="How the pins are labeled"/></p>
<p>The socket side of the connector is the mirror image of this.</p>
<table>
<tr><th>Circular connector pin</th><th>Battery connector pin</th><th>Function</th></tr>
<tr><td>1</td><td></td><td>Unknown</td></tr>
<tr><td>2</td><td></td><td>Unknown</td></tr>
<tr><td>3</td><td></td><td>Unknown</td></tr>
<tr><td>4</td><td>1</td><td>P+</td></tr>
<tr><td>5</td><td>3</td><td>VDD</td></tr>
<tr><td>6</td><td>4</td><td>RX</td></tr>
<tr><td>7</td><td>5</td><td>TX</td></tr>
<tr><td>8</td><td>2</td><td>VCC</td></tr>
<tr><td>9</td><td>6</td><td>P-</td></tr>
<tr><td>10</td><td>6</td><td>P- (yes, connected to pin 9)</td></tr>
<tr><td>A</td><td></td><td>Motor</td></tr>
<tr><td>B</td><td></td><td>Motor</td></tr>
<tr><td>C</td><td></td><td>Motor</td></tr>
</table>
<p>The following drawing hopefully makes this more clear:</p>
<p><img style="display:block;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/kildemoes_teardown/13pin-6pin.svg" alt="How the pins connect to the battery"/></p>
<p>Again, this is looking at the pin side of the 13-pin connector.</p>
<p>If the 13-pin connector is taken apart while the controller/display is powered on then the quiescent current draw drops from 58 mA to 60 µA.
Reconnecting does not bring the display back on,
but it does briefly bring the current up to around 100 µA before settling down to 60 µA again.
When powered on the system runs fine limited to 60 mA.
If the limit is lowered to 50 mA then it dies after a few seconds during which the supply voltage continually drops.</p>
<p>The three pins marked unknown have an as yet unknown function.
I suspect one or two of these pins are used for the magnetic sensor on the rear wheel.
It might be that some of these pins connect to VDD via some of the switches on the display unit, in particular the power switch. I have not tested this yet.</p>
<p>I have not been able to make any of the display LEDs light up via the 13-pin connector.
This and the presence of UART on the 13-pin connector makes me suspect there is a microcontroller in the display.
What is not clear is how exactly power on is dealt with.
Perhaps one of the pins is an enable pin for the controller, asserted by the display?
If so then why does it not seem to connect directly to any supply rail?
VDD is not enabled when the bike is off, but P+ is present on the 13-pin connector.
Perhaps I measured incorrectly.</p>
<p>Only the UART pins and P- (pins 4 through 6) need to be connected between the battery and the control box.
Pin 3 can be supplied from an external 5 V supply.
Pin 2 is not necessary. Applying 5 V to it turns on the light, regardless of whether the bike has booted or if P+ is supplied.
The light can be turned on from the display unit even with pin 2 not connected to the battery.
Pin 1 can be supplied from an external 42 V supply.
The UART pins cannot be swapped around.</p>
<h3>UART</h3>
<p>To sniff UART traffic I have used a USB-to-TTL serial dongle.
Getting it into raw mode requires the following stty incantation: <code>stty -F /dev/ttyUSB0 -echo -icrnl -ixon -onlcr -echoe -echok -echoctl -echoke raw 9600</code>.</p>
<h4>First set of runs</h4>
<p>These runs were made without a battery connected.
The data seen on battery pin 5 (TX) looks as follows:</p>
<div class="highlight"><pre><span></span><code><span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">53</span><span class="w"> </span><span class="mf">05</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">21</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">93</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">53</span><span class="w"> </span><span class="mf">05</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">12</span><span class="w"> </span><span class="mf">21</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="n">A5</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">53</span><span class="w"> </span><span class="mf">05</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">12</span><span class="w"> </span><span class="mf">21</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="n">A5</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">53</span><span class="w"> </span><span class="mf">05</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">12</span><span class="w"> </span><span class="mf">21</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="n">A5</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">52</span><span class="w"> </span><span class="mf">05</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">12</span><span class="w"> </span><span class="mf">49</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="n">CC</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">52</span><span class="w"> </span><span class="mf">05</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="n">AC</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">2</span><span class="n">A</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span><span class="w"> </span><span class="err">[</span><span class="n">this</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="n">repeats</span><span class="w"> </span><span class="n">indefinitely</span><span class="err">]</span>
</code></pre></div>
<p>The data doesn't change between power cycles.
Pin 4 (RX) sees the following data:</p>
<div class="highlight"><pre><span></span><code><span class="mf">00</span><span class="w"> </span><span class="err">[</span><span class="n">stray</span><span class="w"> </span><span class="n">NUL</span><span class="err">?</span><span class="w"> </span><span class="n">present</span><span class="w"> </span><span class="n">in</span><span class="w"> </span><span class="n">all</span><span class="w"> </span><span class="n">dumps</span><span class="err">]</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">53</span><span class="w"> </span><span class="mf">07</span><span class="w"> </span><span class="mf">02</span><span class="w"> </span><span class="mf">40</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">9</span><span class="n">E</span><span class="w"> </span><span class="mf">08</span><span class="w"> </span><span class="mf">7</span><span class="n">F</span><span class="w"> </span><span class="n">DC</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">0</span><span class="n">B</span><span class="w"> </span><span class="mf">2</span><span class="n">F</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">53</span><span class="w"> </span><span class="mf">07</span><span class="w"> </span><span class="mf">02</span><span class="w"> </span><span class="mf">40</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">9</span><span class="n">E</span><span class="w"> </span><span class="mf">08</span><span class="w"> </span><span class="mf">7</span><span class="n">F</span><span class="w"> </span><span class="n">DC</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">0</span><span class="n">B</span><span class="w"> </span><span class="mf">2</span><span class="n">F</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">53</span><span class="w"> </span><span class="mf">07</span><span class="w"> </span><span class="mf">02</span><span class="w"> </span><span class="mf">40</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">9</span><span class="n">E</span><span class="w"> </span><span class="mf">08</span><span class="w"> </span><span class="mf">7</span><span class="n">F</span><span class="w"> </span><span class="n">DC</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">0</span><span class="n">B</span><span class="w"> </span><span class="mf">2</span><span class="n">F</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">53</span><span class="w"> </span><span class="mf">07</span><span class="w"> </span><span class="mf">02</span><span class="w"> </span><span class="mf">40</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">9</span><span class="n">E</span><span class="w"> </span><span class="mf">08</span><span class="w"> </span><span class="mf">7</span><span class="n">F</span><span class="w"> </span><span class="n">DC</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">0</span><span class="n">B</span><span class="w"> </span><span class="mf">2</span><span class="n">F</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">52</span><span class="w"> </span><span class="mf">02</span><span class="w"> </span><span class="mf">75</span><span class="w"> </span><span class="mf">20</span><span class="w"> </span><span class="mf">03</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span><span class="w"> </span><span class="err">[</span><span class="n">this</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="n">repeats</span><span class="w"> </span><span class="n">indefinitely</span><span class="err">]</span>
</code></pre></div>
<p>So when the error LED is blinking, TX sees <code>3A 1A 52 05 00 00 0D AC 00 2A 01 0D 0A</code>, then RX sees <code>3A 1A 52 02 75 20 03 01 0D 0A</code> a few ms later.
This happens roughly twice per second.</p>
<p>I suspect the data seen here is between the ESC and the display.
Since I don't know which of these two is the master device I don't know in which directions the data flows.</p>
<h4>Second set of runs</h4>
<p>In a second set of runs with a battery connected the following data were observed.
TX (pin 5), run #1:</p>
<div class="highlight"><pre><span></span><code><span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">53</span><span class="w"> </span><span class="mf">05</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">21</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">93</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">02</span><span class="w"> </span><span class="mf">58</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">7</span><span class="n">D</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">53</span><span class="w"> </span><span class="mf">05</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">12</span><span class="w"> </span><span class="mf">21</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="n">A5</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">02</span><span class="w"> </span><span class="mf">58</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">7</span><span class="n">D</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">53</span><span class="w"> </span><span class="mf">05</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">12</span><span class="w"> </span><span class="mf">21</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="n">A5</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">02</span><span class="w"> </span><span class="mf">58</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">7</span><span class="n">D</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">53</span><span class="w"> </span><span class="mf">05</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">12</span><span class="w"> </span><span class="mf">21</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="n">A5</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">02</span><span class="w"> </span><span class="mf">58</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">7</span><span class="n">D</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">02</span><span class="w"> </span><span class="mf">58</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">7</span><span class="n">D</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">02</span><span class="w"> </span><span class="mf">58</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">7</span><span class="n">D</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">52</span><span class="w"> </span><span class="mf">05</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="n">AC</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">2</span><span class="n">A</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="err">[</span><span class="n">the</span><span class="w"> </span><span class="n">last</span><span class="w"> </span><span class="n">two</span><span class="w"> </span><span class="n">lines</span><span class="w"> </span><span class="n">repeat</span><span class="w"> </span><span class="n">indefinitely</span><span class="err">]</span>
</code></pre></div>
<p>Run #2:</p>
<div class="highlight"><pre><span></span><code><span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">53</span><span class="w"> </span><span class="mf">05</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">21</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">93</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">02</span><span class="w"> </span><span class="mf">59</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">7</span><span class="n">E</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">53</span><span class="w"> </span><span class="mf">05</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">12</span><span class="w"> </span><span class="mf">21</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="n">A5</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">02</span><span class="w"> </span><span class="mf">59</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">7</span><span class="n">E</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">53</span><span class="w"> </span><span class="mf">05</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">12</span><span class="w"> </span><span class="mf">21</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="n">A5</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">02</span><span class="w"> </span><span class="mf">59</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">7</span><span class="n">E</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">53</span><span class="w"> </span><span class="mf">05</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">12</span><span class="w"> </span><span class="mf">21</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="n">A5</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">02</span><span class="w"> </span><span class="mf">59</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">7</span><span class="n">E</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">02</span><span class="w"> </span><span class="mf">59</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">7</span><span class="n">E</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">02</span><span class="w"> </span><span class="mf">59</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">7</span><span class="n">E</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">52</span><span class="w"> </span><span class="mf">05</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="n">AC</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">2</span><span class="n">A</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="err">[</span><span class="n">the</span><span class="w"> </span><span class="n">last</span><span class="w"> </span><span class="n">two</span><span class="w"> </span><span class="n">lines</span><span class="w"> </span><span class="n">repeat</span><span class="w"> </span><span class="n">indefinitely</span><span class="err">]</span>
</code></pre></div>
<p>RX (pin 4), both runs:</p>
<div class="highlight"><pre><span></span><code><span class="mf">00</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">53</span><span class="w"> </span><span class="mf">07</span><span class="w"> </span><span class="mf">02</span><span class="w"> </span><span class="mf">40</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">9</span><span class="n">E</span><span class="w"> </span><span class="mf">08</span><span class="w"> </span><span class="mf">7</span><span class="n">F</span><span class="w"> </span><span class="n">DC</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">0</span><span class="n">B</span><span class="w"> </span><span class="mf">2</span><span class="n">F</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">53</span><span class="w"> </span><span class="mf">07</span><span class="w"> </span><span class="mf">02</span><span class="w"> </span><span class="mf">40</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">9</span><span class="n">E</span><span class="w"> </span><span class="mf">08</span><span class="w"> </span><span class="mf">7</span><span class="n">F</span><span class="w"> </span><span class="n">DC</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">0</span><span class="n">B</span><span class="w"> </span><span class="mf">2</span><span class="n">F</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">53</span><span class="w"> </span><span class="mf">07</span><span class="w"> </span><span class="mf">02</span><span class="w"> </span><span class="mf">40</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">9</span><span class="n">E</span><span class="w"> </span><span class="mf">08</span><span class="w"> </span><span class="mf">7</span><span class="n">F</span><span class="w"> </span><span class="n">DC</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">0</span><span class="n">B</span><span class="w"> </span><span class="mf">2</span><span class="n">F</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">53</span><span class="w"> </span><span class="mf">07</span><span class="w"> </span><span class="mf">02</span><span class="w"> </span><span class="mf">40</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">9</span><span class="n">E</span><span class="w"> </span><span class="mf">08</span><span class="w"> </span><span class="mf">7</span><span class="n">F</span><span class="w"> </span><span class="n">DC</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">0</span><span class="n">B</span><span class="w"> </span><span class="mf">2</span><span class="n">F</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">01</span><span class="w"> </span><span class="mf">0</span><span class="n">B</span><span class="w"> </span><span class="mf">2</span><span class="n">F</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="mf">3</span><span class="n">A</span><span class="w"> </span><span class="mf">1</span><span class="n">A</span><span class="w"> </span><span class="mf">52</span><span class="w"> </span><span class="mf">02</span><span class="w"> </span><span class="mf">75</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="n">E3</span><span class="w"> </span><span class="mf">00</span><span class="w"> </span><span class="mf">0</span><span class="n">D</span><span class="w"> </span><span class="mf">0</span><span class="n">A</span>
<span class="err">[</span><span class="n">the</span><span class="w"> </span><span class="n">last</span><span class="w"> </span><span class="n">two</span><span class="w"> </span><span class="n">lines</span><span class="w"> </span><span class="n">repeat</span><span class="w"> </span><span class="n">indefinitely</span><span class="err">]</span>
</code></pre></div>
<p>A 1k resistor must be inserted between the USB-TTL dongle's RX and pin 4 or else the display will error out, indicating a weak drive.
If either pin is disconnected then an error is displayed after a few seconds or two.</p>
<h3>Side by side comparisons of both sets of runs</h3>
<p>This section is very WIP.
TX:</p>
<div class="highlight"><pre><span></span><code><span class="k">No</span><span class="w"> </span><span class="n">battery</span><span class="w"> </span><span class="n">Battery</span><span class="w"> </span><span class="n">run</span><span class="w"> </span><span class="n">#1</span><span class="w"> </span><span class="n">Battery</span><span class="w"> </span><span class="n">run</span><span class="w"> </span><span class="n">#2</span>
<span class="mi">3</span><span class="n">A</span><span class="w"> </span><span class="mi">1</span><span class="n">A</span><span class="w"> </span><span class="mi">53</span><span class="w"> </span><span class="mi">05</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">21</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">93</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">0</span><span class="n">A</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span>
<span class="w"> </span><span class="mi">3</span><span class="n">A</span><span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">58</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">7</span><span class="n">D</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">0</span><span class="n">A</span><span class="w"> </span><span class="mi">3</span><span class="n">A</span><span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">59</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">7</span><span class="n">E</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">0</span><span class="n">A</span>
<span class="mi">3</span><span class="n">A</span><span class="w"> </span><span class="mi">1</span><span class="n">A</span><span class="w"> </span><span class="mi">53</span><span class="w"> </span><span class="mi">05</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">12</span><span class="w"> </span><span class="mi">21</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="n">A5</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">0</span><span class="n">A</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span>
<span class="w"> </span><span class="mi">3</span><span class="n">A</span><span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">58</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">7</span><span class="n">D</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">0</span><span class="n">A</span><span class="w"> </span><span class="mi">3</span><span class="n">A</span><span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">59</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">7</span><span class="n">E</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">0</span><span class="n">A</span>
<span class="mi">3</span><span class="n">A</span><span class="w"> </span><span class="mi">1</span><span class="n">A</span><span class="w"> </span><span class="mi">53</span><span class="w"> </span><span class="mi">05</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">12</span><span class="w"> </span><span class="mi">21</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="n">A5</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">0</span><span class="n">A</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span>
<span class="w"> </span><span class="mi">3</span><span class="n">A</span><span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">58</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">7</span><span class="n">D</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">0</span><span class="n">A</span><span class="w"> </span><span class="mi">3</span><span class="n">A</span><span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">59</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">7</span><span class="n">E</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">0</span><span class="n">A</span>
<span class="mi">3</span><span class="n">A</span><span class="w"> </span><span class="mi">1</span><span class="n">A</span><span class="w"> </span><span class="mi">53</span><span class="w"> </span><span class="mi">05</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">12</span><span class="w"> </span><span class="mi">21</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="n">A5</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">0</span><span class="n">A</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span>
<span class="w"> </span><span class="mi">3</span><span class="n">A</span><span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">58</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">7</span><span class="n">D</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">0</span><span class="n">A</span><span class="w"> </span><span class="mi">3</span><span class="n">A</span><span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">59</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">7</span><span class="n">E</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">0</span><span class="n">A</span>
<span class="w"> </span><span class="mi">3</span><span class="n">A</span><span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">58</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">7</span><span class="n">D</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">0</span><span class="n">A</span><span class="w"> </span><span class="mi">3</span><span class="n">A</span><span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">59</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">7</span><span class="n">E</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">0</span><span class="n">A</span>
<span class="w"> </span><span class="mi">3</span><span class="n">A</span><span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">58</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">7</span><span class="n">D</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">0</span><span class="n">A</span><span class="w"> </span><span class="mi">3</span><span class="n">A</span><span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">59</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">7</span><span class="n">E</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">0</span><span class="n">A</span>
<span class="mi">3</span><span class="n">A</span><span class="w"> </span><span class="mi">1</span><span class="n">A</span><span class="w"> </span><span class="mi">52</span><span class="w"> </span><span class="mi">05</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">12</span><span class="w"> </span><span class="mi">49</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="n">CC</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">0</span><span class="n">A</span>
<span class="mi">3</span><span class="n">A</span><span class="w"> </span><span class="mi">1</span><span class="n">A</span><span class="w"> </span><span class="mi">52</span><span class="w"> </span><span class="mi">05</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="n">AC</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">2</span><span class="n">A</span><span class="w"> </span><span class="mi">01</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">0</span><span class="n">A</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span>
<span class="o">[</span><span class="n">the last two lines repeat indefinitely</span><span class="o">]</span>
</code></pre></div>
<p>There is more data sent when a battery is present.
Looking more closely at the data that differs between battery runs:</p>
<blockquote>
<p>3A 16 0D 02 <strong>58</strong> 00 <strong>7D</strong> 00 0D 0A<br/>
3A 16 0D 02 <strong>59</strong> 00 <strong>7E</strong> 00 0D 0A</p>
</blockquote>
<p>The last two bytes appear to be 16-bit checksums of all bytes but the initial 3A.
Specifically byte sums in little endian order:</p>
<blockquote>
<p>16 + 0D + 02 + 58 + 00 = 0x007D = 7D 00<br/>
16 + 0D + 02 + 59 + 00 = 0x007E = 7E 00</p>
</blockquote>
<p>Cutting out the initial 3A, the checksums and CRLF we can simplify TX to this:</p>
<div class="highlight"><pre><span></span><code><span class="k">No</span><span class="w"> </span><span class="n">battery</span><span class="w"> </span><span class="n">Battery</span><span class="w"> </span><span class="n">run</span><span class="w"> </span><span class="n">#1</span><span class="w"> </span><span class="n">Battery</span><span class="w"> </span><span class="n">run</span><span class="w"> </span><span class="n">#2</span>
<span class="mi">1</span><span class="n">A</span><span class="w"> </span><span class="mi">53</span><span class="w"> </span><span class="mi">05</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">21</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span>
<span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">58</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">59</span><span class="w"> </span><span class="mi">00</span>
<span class="mi">1</span><span class="n">A</span><span class="w"> </span><span class="mi">53</span><span class="w"> </span><span class="mi">05</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">12</span><span class="w"> </span><span class="mi">21</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span>
<span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">58</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">59</span><span class="w"> </span><span class="mi">00</span>
<span class="mi">1</span><span class="n">A</span><span class="w"> </span><span class="mi">53</span><span class="w"> </span><span class="mi">05</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">12</span><span class="w"> </span><span class="mi">21</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span>
<span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">58</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">59</span><span class="w"> </span><span class="mi">00</span>
<span class="mi">1</span><span class="n">A</span><span class="w"> </span><span class="mi">53</span><span class="w"> </span><span class="mi">05</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">12</span><span class="w"> </span><span class="mi">21</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span>
<span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">58</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">59</span><span class="w"> </span><span class="mi">00</span>
<span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">58</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">59</span><span class="w"> </span><span class="mi">00</span>
<span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">58</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">59</span><span class="w"> </span><span class="mi">00</span>
<span class="mi">1</span><span class="n">A</span><span class="w"> </span><span class="mi">52</span><span class="w"> </span><span class="mi">05</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">12</span><span class="w"> </span><span class="mi">49</span><span class="w"> </span><span class="mi">00</span>
<span class="mi">1</span><span class="n">A</span><span class="w"> </span><span class="mi">52</span><span class="w"> </span><span class="mi">05</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="n">AC</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span>
<span class="o">[</span><span class="n">the last two lines repeat indefinitely</span><span class="o">]</span>
</code></pre></div>
<p>Since TX here is from the battery's POV, <code>16 0D 02 XX 00</code> must be data coming from the battery and <code>1A 53 05 00 00 00 21 00</code> comes from the other slave device in the system.</p>
<p>Note the extra <code>1A 52 05 00 00 12 49 00</code> transmission in the no-battery run.
Perhaps it tells the display to signal an error?
Or if the ESC is slaved to the display, to refuse to turn the motor?</p>
<p>RX with the same kind of simplification, and stripping the initial NUL:</p>
<div class="highlight"><pre><span></span><code><span class="k">No</span><span class="w"> </span><span class="n">battery</span><span class="w"> </span><span class="n">Battery</span><span class="w"> </span><span class="n">run</span><span class="w"> </span><span class="p">(</span><span class="k">both</span><span class="p">)</span>
<span class="mi">1</span><span class="n">A</span><span class="w"> </span><span class="mi">53</span><span class="w"> </span><span class="mi">07</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">40</span><span class="w"> </span><span class="mi">01</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">9</span><span class="n">E</span><span class="w"> </span><span class="mi">08</span><span class="w"> </span><span class="mi">7</span><span class="n">F</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span>
<span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">01</span><span class="w"> </span><span class="mi">0</span><span class="n">B</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span>
<span class="mi">1</span><span class="n">A</span><span class="w"> </span><span class="mi">53</span><span class="w"> </span><span class="mi">07</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">40</span><span class="w"> </span><span class="mi">01</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">9</span><span class="n">E</span><span class="w"> </span><span class="mi">08</span><span class="w"> </span><span class="mi">7</span><span class="n">F</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span>
<span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">01</span><span class="w"> </span><span class="mi">0</span><span class="n">B</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span>
<span class="mi">1</span><span class="n">A</span><span class="w"> </span><span class="mi">53</span><span class="w"> </span><span class="mi">07</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">40</span><span class="w"> </span><span class="mi">01</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">9</span><span class="n">E</span><span class="w"> </span><span class="mi">08</span><span class="w"> </span><span class="mi">7</span><span class="n">F</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span>
<span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">01</span><span class="w"> </span><span class="mi">0</span><span class="n">B</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span>
<span class="mi">1</span><span class="n">A</span><span class="w"> </span><span class="mi">53</span><span class="w"> </span><span class="mi">07</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">40</span><span class="w"> </span><span class="mi">01</span><span class="w"> </span><span class="mi">00</span><span class="w"> </span><span class="mi">9</span><span class="n">E</span><span class="w"> </span><span class="mi">08</span><span class="w"> </span><span class="mi">7</span><span class="n">F</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span>
<span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">01</span><span class="w"> </span><span class="mi">0</span><span class="n">B</span><span class="w"> </span><span class="o">[</span><span class="n">identical</span><span class="o">]</span>
<span class="w"> </span><span class="mi">16</span><span class="w"> </span><span class="mi">0</span><span class="n">D</span><span class="w"> </span><span class="mi">01</span><span class="w"> </span><span class="mi">0</span><span class="n">B</span><span class="w"> </span><span class="o">[</span><span class="n">same as last line</span><span class="o">]</span>
<span class="mi">1</span><span class="n">A</span><span class="w"> </span><span class="mi">52</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">75</span><span class="w"> </span><span class="mi">20</span><span class="w"> </span><span class="mi">1</span><span class="n">A</span><span class="w"> </span><span class="mi">52</span><span class="w"> </span><span class="mi">02</span><span class="w"> </span><span class="mi">75</span><span class="w"> </span><span class="mi">00</span>
<span class="o">[</span><span class="n">last line repeats indefinitely</span><span class="o">]</span>
</code></pre></div>
<p>We see the 1A and 16 line up nicely with rows in the TX dump, indicating that <code>16 0D</code> is the address for the battery and <code>1A 53</code> to the other device.
So the command being sent to the battery is just <code>01 0B</code> to which the battery replies <code>02 XX 00</code>.</p>
<p>Note that the longer messages <code>(3A) 1A 53 07 02 40 01 00 9E 08 7F (DC 01 0D 0A)</code> have enough bytes where the checksum exceeds FF, in this case 0x01DC, verifying that they are indeed 16-bit.</p>
<p>Perhaps the extra <code>16 0D 01 0B</code> activates the ESC? Unlikely.
As for the repeating data, let's look more closely:</p>
<blockquote>
<p>1A 52 02 75 <strong>20</strong><br/>
1A 52 02 75 <strong>00</strong></p>
</blockquote>
<p>Only a single bit different.
Perhaps this is what actually tells the system to not run the motor?
Note also the that the address is <code>1A 52</code> not <code>1A 53</code>.
A hack to get the system to work with a custom battery might be to pull the RX bus low for this bit.
This should be easy since the bus is so weakly driven.</p>
<h2>Battery</h2>
<p>The battery is a Phylion Joycube.
It is a 10S4P battery, meaning 36 V nominal, 42 V when fully charged.
They come in at least 8.8 Ah (2200 mAh cells) and 11.6 Ah variants (2900 mAh cells).
It has a "smart BMS" which I suspect is an anti-competition/anti-third-party-market feature,
at least from Crescent's point of view.
Phylion likely provides this just as a useful feature.</p>
<p>The battery is held together with six PH2 screws on the bottom and two PH1 screws in the charge port.
Some amount of force is required to pull the battery shell apart.</p>
<p>The BMS board contains an STM32 (<a href="https://www.st.com/en/microcontrollers-microprocessors/stm32f072cb.html">F072C8T6</a>) and a BMS chip (<a href="https://www.ti.com/lit/ds/symlink/bq76920.pdf">bq7694003</a>).
RX and TX are marked.
There are two optoisolators (<a href="https://www.sparkfun.com/datasheets/Components/ps2501.pdf">2501-1</a>), for the RX and TX pins.</p>
<p>There are two pairs of <a href="https://static.chipdip.ru/lib/920/DOC012920924.pdf">NCE80H12</a> N-channel MOSFETs (80V 120A).
These are driven by a FET driver (<a href="https://www.ti.com/lit/ds/symlink/bq76200.pdf">bq7620b</a>) on the bottom of the board,
connected to the gates to each pair of MOSFETs through 100 Ohm resistors.</p>Prices and information part 22021-11-17T12:40:51+01:002021-11-17T12:40:51+01:00tomastag:www.härdin.se,2021-11-17:/blog/2021/11/17/prices-and-information-part-2/<p><a href="http://www.härdin.se/blog/2021/11/14/prices-and-information/">My previous post</a> has received some feedback from Paul Cockshott on <a href="https://twitter.com/PaulCockshott/status/1460181384731967490">Twitter</a> (<a href="https://nitter.pussthecat.org/PaulCockshott/status/1460181384731967490#m">nitter link</a>). I have responded to this over email, but I thought I should post it here too. I've also had some additional thoughts in the last three days that I have added further down.</p>
<blockquote>
<p>Hardin is being …</p></blockquote><p><a href="http://www.härdin.se/blog/2021/11/14/prices-and-information/">My previous post</a> has received some feedback from Paul Cockshott on <a href="https://twitter.com/PaulCockshott/status/1460181384731967490">Twitter</a> (<a href="https://nitter.pussthecat.org/PaulCockshott/status/1460181384731967490#m">nitter link</a>). I have responded to this over email, but I thought I should post it here too. I've also had some additional thoughts in the last three days that I have added further down.</p>
<blockquote>
<p>Hardin is being over generous to the Misereans</p>
<p>I think 26 bits is overestimating </p>
<p>It is leaving out uncertainty. Go round 5 shops selling cauliflowers they will not all sell at the same price to the last cent or penny. One may be 90p, one may be £1.00, one may be 95p etc. One really needs to have a two level analysis</p>
<ol>
<li>
<p>The % uncertainty for a given commodity : cauliflowers, loaves of bread, etc - say this is 10%</p>
</li>
<li>
<p>The dynamic range contrasting cauliflowers with really expensive things like nuclear submarines. So what you need is a floating point representation with perhaps 7 bits of mantissa and an exponent. I am pretty sure you could handle it with 16 bit IEEE floating point</p>
</li>
</ol>
</blockquote>
<p>It is true that commodities have different prices locally.
But with stocks and the futures market you end up with a single global price, or very nearly so. This thanks to mechanisms like arbitrage.</p>
<p>The point isn't really the exact number of bits, but rather that it is a small number of bits and that it is a projection of many things onto a scalar. The Austrian argument is that this is good because it makes apples and oranges commensurable. My point is the opposite. In planning we have a much richer collection of data to work with. We can think in terms of use-values rather than just exchange-values.
We don't compare apples and oranges, but rather make sure there's enough of both for everyone.
If investing in machinery is not enough to meet demand then we must either use remuneration, a lottery or rationing to distribute the limited supply.</p>
<p>Regarding planning having access to richer data, remember that prices supposedly contain information about supply and demand.
But how much information actually makes up supply and demand themselves?
For simplicity I will focus only on demand.</p>
<p>Let us assume we are dealing with goods that are consumed in integer amounts, for example cars.
Assume everyone wants either zero or one cars of a certain type.
Call the total number of cars <em>k</em> and the number of people <em>n</em>.
Then the amount of information is at most <math>
<mrow><mi>E</mi><mo lspace="0.278em" rspace="0.278em">=</mo><msub><mi>log</mi><mn>2</mn></msub><mspace width="0.167em"/><mrow><mo stretchy="true">(</mo><mrow><mfrac linethickness="0"><mi>n</mi><mi>k</mi></mfrac></mrow><mo stretchy="true">)</mo></mrow></mrow>
</math>.
If we have some way to estimate which people are actually interested in this specific car then <em>n</em> shrinks and so does <em>E</em>.
It doesn't take much for <em>E</em> to exceed the very generous 26.6 bits.
A single car in a population of 100,000,000 or two cars among 14,000 people.
If half the population wants a car then <em>E</em> is just below <em>n</em> bits,
or eight gigabits for the current size of the world population.
Clearly this is much larger than 26.6 bits.
Therefore prices must always be a very aggregated and approximate piece of information.
Yet somehow to the Austrians, the market is the best way of fulfilling demand.
But the market can't actually know the demand because the price mechanism doesn't contain enough information to properly signal it.
A similar argument can be made for supply.</p>
<p>I have by this point talked to Austrians online enough times to know that, as praxeologists, they don't actually care about mathematical points like this one.
When confronted with evidence that contradicts the ECP they will just shift the discussion instead.
"You can't compute this" becomes "you can't gather the necessary data" becomes "actually it's about enterpreneurship".
Nevermind that enterpreneurship is perfectly compatible with planning or that in a socialist economy we can implement <em>more</em> of people's ideas, ideas that are currently left undeveloped because they are not profitable.
Doing stuff outside the profit motive, especially deciding democratically to tackle climate change, is unthinkable to these people, since it amounts to putting oneself above God-the-market.</p>Prices and information2021-11-14T16:10:00+01:002021-11-14T16:10:00+01:00tomastag:www.härdin.se,2021-11-14:/blog/2021/11/14/prices-and-information/<p>A common talking point from Austrian economists is that prices encode people's subjective preferences.
This notion has not been examined from an information theoretical point of view as far as I can tell.
So let's look at it.</p>
<p>The price of a commodity is a definite value in some currency …</p><p>A common talking point from Austrian economists is that prices encode people's subjective preferences.
This notion has not been examined from an information theoretical point of view as far as I can tell.
So let's look at it.</p>
<p>The price of a commodity is a definite value in some currency.
Prices are discrete values that correspond to a definite amount of information.
Prices cannot be real-valued, they must be discrete, because humans and computers have finite information processing capabilities.
The world market runs on actual computers sending actual bits around,
on people sending letters and invoices with discrete characters written on them.</p>
<p>If for example we have a market where things are priced in cents, and the range of prices are from zero to say $999,999.99, then the information content of any price is at most log<sub>2</sub>(10⁸) ≃ 26.6 bits.
Actual prices will contain less information than this since prices are not uniformly distributed in any given range.
Let's say we do statistics on prices in the market and we come up with a number of 20 bits.
If we have a good predictor for the value of a commodity, then the information content of each price goes down further still.
In the Marxist camp the go-to predictor of prices are labour values, which account for some 93% of variations seen in prices last time I checked the literature.
This means that the residual amount of information is 20 + log<sub>2</sub>(1 - 0.93) ≃ 16.2 bits.
If we find a better predictor then the information content drops even more.
In practice there will be some lower bound.
A 99.9% accurate predictor still leaves 10.0 bits unaccounted for in this example.</p>
<p>Prices change over time, and such changes correspond also to definite amounts of information being signalled.
They are less than the information content in the price itself, because prices don't fluctuate uniformly randomly.
If the value of a commodity changes then its price tends to change as well, sooner or later.
If our predictor is good then the information contained in the price change is small.
If the price changes frequently then the mass of information signalled will be large.
This does not necessarily mean that the information is actually useful, merely that some amount of information is being sent around.
For all we know the price may be functionally equivalent to a Ouija board.</p>
<p>If the price changes frequently but the range within which it fluctuates is very small, then the mass of information contained will be smaller than if the price changes over a larger range.
It may even be smaller than much more infrequent price changes of larger magnitude.</p>
<h2>Conclusion</h2>
<p>The Austrians are partly correct in that the price system is an approximate way of signalling supply and demand in the market.
It is a feedback mechanism.
But the amount of information being signalled at any one time is quite small, and it is only a scalar value.
At every point in time the subjective preferences of every actor in the market must be projected down and quantized to a definite price.
Prices don't "encode" things in the sense that we can decode them later.
It is a lossy process.</p>
<p>In planning (calculation in kind) the loss of information from a projection down to a scalar price does not happen.
We also have available information of supply and demand explicitly, rather than implicitly.
Supply is determined by the means of production currently available.
Demand is measured and predicted.
If necessary we can put limits on demand by a remuneration system,
to prevent people from making demands of the system that would make the plan infeasible.</p>
<p>Since the demand vector comes from all consumers, each consumer participates in steering production.
On the supply side we similarly want as many people as possible to at least be able to test their ideas for new productive methods.
Everyone then participates in shaping the feasible region of the mathematical program from which the plan is derived.
These are two ways in which democratic planning addresses the local knowledge problem.
Democracy is important, not for moral reasons, but for being able to capture as much and as fine-grained demand information as possible, and to capture good ideas that are currently ignored by the market system.
This allows democratic planning to surpass the market in terms of meeting demands and enabling human flourishing.</p>Site updates2021-10-20T10:09:21+02:002021-10-20T10:09:21+02:00tomastag:www.härdin.se,2021-10-20:/blog/2021/10/20/site-updates/<ul>
<li>reverted "text-align: justify" in CSS. HTML isn't good at pretending to be LaTeX</li>
<li>fixed margins on narrow screens</li>
<li>updated IRC contact information to libera.chat</li>
<li>changed links to kicad-pcb.org to kicad.org (<a href="https://www.kicad.org/blog/2021/10/Avoid-links-to-former-kicad-domain/">see this post on kicad.org</a>)</li>
<li>fixed accidentally removing all .exe files in the file archive, which …</li></ul><ul>
<li>reverted "text-align: justify" in CSS. HTML isn't good at pretending to be LaTeX</li>
<li>fixed margins on narrow screens</li>
<li>updated IRC contact information to libera.chat</li>
<li>changed links to kicad-pcb.org to kicad.org (<a href="https://www.kicad.org/blog/2021/10/Avoid-links-to-former-kicad-domain/">see this post on kicad.org</a>)</li>
<li>fixed accidentally removing all .exe files in the file archive, which affected the <a href="/files/bg2/">BG2 file archive</a> and the <a href="/files/wasteland-thewastes/old-ftp/">Wasteland Half-Life/The Wastes file archive</a></li>
</ul>
<p>I've also ordered a whole heap of books related to socialist planning. Consulting and electronics work is taking up my time at the moment.</p>Room cooler2021-07-12T13:13:46+02:002021-07-12T13:13:46+02:00tomastag:www.härdin.se,2021-07-12:/blog/2021/07/12/room-cooler/<p>Due to the increasingly hot summers here in Sweden,
I wanted something I could use to keep my apartment cool during the worst days.
Air conditioning units can be had for 250-500€.
This is a bit on the high side for how many days per year they'd actually be used …</p><p>Due to the increasingly hot summers here in Sweden,
I wanted something I could use to keep my apartment cool during the worst days.
Air conditioning units can be had for 250-500€.
This is a bit on the high side for how many days per year they'd actually be used,
and there is the problem of getting rid of waste heat.</p>
<p>Three or four years ago me and a friend built a rig for another friend of ours to keep his apartment cool,
out of a PC water cooling radiator+fan and some plumbing parts.
Cold water from the tap enters the radiator, and waste water is simply flushed down the drain.
This worked out quite well, so I decided to replicate this idea using parts I had on hand or that I could find in the local hackerspace.
The result was the picture below:</p>
<p><a href="http://www.härdin.se/images/room_cooler/P7122179.JPG"><img alt="The cooler itself." src="http://www.härdin.se/images/room_cooler/tP7122179.JPG"></a></p>
<p>The radiator is from a car and measures 22x20x5 cm.
The fans are a bunch of old server fans, mostly Delta brand.
This means the cooler is very noisy - around 63 dBA.
Total air flow is 7.7 m³/minute for 60 W total fan power,
not accounting for the pressure drop through the radiator.</p>
<p>The fans are mounted to a thin MDF board, and the board itself has a "border" made of 5-6 layers of double-sided tape acting as a seal.
The board is secured to the radiator using zip ties.
An old PSU supplies the 12 V.</p>
<p>Using a digital thermometer and a timer I was able to determine the temperature difference and flow rates for two different settings on the faucet.
From this I was able to determine the cooling power.
The results are listed in the table below:</p>
<table>
<tr><th>Flow rate (ml/s (l/h))</th><th>Temperature diff (°C)</th><th>Cooling power (W (BTU/h))</th><th>Efficiency (J/ml)</th></tr>
<tr><td>6.49 (23.4)</td><td>7.7</td><td>209 (713)</td><td>32.2</td></tr>
<tr><td>24.4 (87.8)</td><td>5.5</td><td>561 (1914)</td><td>23.0</td></tr>
</table>
<p>Higher flow rates means more cooling, but also more wasteful use of water.
The inlet water was cooler during the higher flow test, 12.8°C vs 16.6°C, which has likely skewed the results.
Room temperature remained around 24-26°C.</p>
<p>All in all this works well enough to cool the area around my bed.
The noise keeps it from being useful at night or when I'm reading, unless I replace the PSU with an adjustable supply.
A better passive solution would be to install awnings on the south wall of the building to keep the sun from warming up the inside,
but unfortunately I'm not allowed to do that since it's owned by the municipality.</p>A critique of Economic Calculation in the Socialist Commonwealth2021-06-29T23:09:28+02:002021-06-29T23:09:28+02:00tomastag:www.härdin.se,2021-06-29:/blog/2021/06/29/a-critique-of-economic-calculation-in-the-socialist-commonwealth/<p>In this post I will critique <a href="https://en.wikipedia.org/wiki/Ludwig_von_Mises">Ludwig von Mises'</a> classic polemic against socialist planning,
<em>Economic Calculation in the Socialist Commonwealth</em>, published in 1920.
In this text Mises introduces the Economic Calculation Problem (ECP).
I will quote segments of the text and highlight what effects 100 years of advance in the …</p><p>In this post I will critique <a href="https://en.wikipedia.org/wiki/Ludwig_von_Mises">Ludwig von Mises'</a> classic polemic against socialist planning,
<em>Economic Calculation in the Socialist Commonwealth</em>, published in 1920.
In this text Mises introduces the Economic Calculation Problem (ECP).
I will quote segments of the text and highlight what effects 100 years of advance in the field of computation has had on the Mises' arguments.
A copy of the text is available <a href="https://web.archive.org/web/20141216200523/http://library.freecapitalists.org/books/Ludwig%20von%20Mises/Economic%20Calculation%20in%20the%20Socialist%20Commonwealth.pdf">here from archive.org</a>.</p>
<p>I have broken down this critique on a chapter-by-chapter basis.</p>
<p>2024-02-27: I made a <a href="http://www.härdin.se/blog/2022/11/04/video-version-of-my-mises-critique/">video version of this critique</a> some time ago. Check it out!</p>
<h2>1. The Distribution of Consumption Goods in the Socialist Commonwealth</h2>
<p>In this chapter Mises correctly identifies that "who is to do the consuming and what is to be consumed by each is the crux of the problem of socialist distribution".
These two problems correspond to the remuneration problem and measuring/predicting demand.</p>
<blockquote>
<p>It is characteristic of socialism that the distribution of consumption goods must be independent of the question of production and of its economic conditions.</p>
</blockquote>
<p>This statement is wrong, partly because distribution of both final and intermediate goods happens on the same transportation network.
In addition, what final goods that can even be offered depends on the state of the productive forces.
Thirdly, there is an overlap between the two groups of goods.
Flour is both a consumer good, and a means of producing bread in a bakery.
Fuel is both a consumer good, and a vitally important resource in the distribution process.</p>
<blockquote>
<p>For, as we shall show, it lies in the very nature of socialist production that the shares of the particular factors of production in the national dividend cannot be ascertained, and that it is impossible in fact to gauge the relationship between expenditure and income.</p>
</blockquote>
<p>This is equivalent to saying technological coefficients cannot be measured.
We know this to be false.</p>
<p>Then comes a few sections implying that the State decides how goods are to be distributed,
and that remuneration would be done with ration coupons,
based on some <em>a priori</em> distribution.
To Mises' credit it is not out of the question that certain goods might be subject to rationing,
in particular goods that are scarce and in high demand, for example fossil fuel.
But for all other goods there is no need to do this.
In the model proposed by Paul Cockshott and Allinn Cottrell in their book <em>Towards a New Socialism</em>, an estimate of final demand is computed based on sales in publicly run stores.
If the estimate is wrong then sales data provide feedback to the planning system to increase or decrease production of some final good.
A small excess can also be explicitly planned for, say 1-5%, on the grounds that overproduction is not as bad as underproduction.</p>
<p>Mises is correct that calculating the price of production goods in terms of money is impossible in a socialist system.
This is a consequence of calculation in kind.</p>
<p>Further in Mises points to the limited fungibility of labour, among other things asserting that:</p>
<blockquote>
<p>Yet one cannot allow the laborer who had put in an hour of the most simple type of labor to be entitled to the product of an hour’s higher type of labor.</p>
</blockquote>
<p>But such "higher" labour is itself the product of labour, namely teaching and studying.
A medical professional will have absorbed more labour before they begin working than the average worker will have absorbed.
Therefore medical workers are more valuable.
This doesn't necessarily mean medical workers would be paid more, only that it costs society more to train them.
We <em>could</em> choose to pay medical workers more, but we could also choose to pay people for studying medicine.</p>
<p>I also don't subscribe to the notion of there being "higher" and "lower" forms of labour.
There are merely <em>different</em> forms, all of which require different amounts of training to perform.
Proficiency is a vector value, not a scalar.</p>
<p>Mises ends the chapter with the following:</p>
<blockquote>
<p>For, over and above the actual labor, the production of all economic goods entails also the cost of materials. An article in which more raw material is used can never be reckoned of equal value with one in which less is used.</p>
</blockquote>
<p>I wonder whether Mises had actually read any of the classical economists before writing this,
since none of them suggest that one can ignore the cost of raw materials.</p>
<p>It is very easy to imagine two goods that have the same value, are made of the same raw material but one uses more of it than the other.
One example of this is copper ingots vs copper tubing.
Ingots are easier to produce than tubing, and so have less social labour embodied per kilogram than does tubing.
Therefore a mass X of ingots and Y of tubing, where X > Y, may indeed have the same value.</p>
<p>If Mises is talking about equivalent goods here, say copper ingots from two different foundries, then of course equal amounts have equal value (unless of course you get your copper ingots from <a href="https://en.wikipedia.org/wiki/Complaint_tablet_to_Ea-nasir">Ea-nasir</a>).</p>
<h2>2. The Nature of Economic Calculation</h2>
<p>Here Mises confuses use-value with value, a trait he shares with neoclassical economists.
It is obvious that different people have different wants, that use-value is in the eye of the beholder.
Mises then points out that it is exchange-value that is useful in trade, not use-value.
This is of course correct.
Mises then says that because market relations play out a certain way, then that way is "the appropriate employment of goods".
An obvious counter to this is to point out that short-sighted employment of goods like petroleum are most definitely not "appropriate".
On top of this there is the problem of market manipulation.</p>
<p>After a comparison to the fictional Robinson Crusoe, Mises makes this claim:</p>
<blockquote>
<p>That [taking into consideration the intersubstitutability of goods] is only
possible in very simple conditions is obvious. In the case of more complicated
and more lengthy processes of production it will, plainly, not answer.</p>
<p>Anyone who wishes to make calculations in regard to a
complicated process of production will immediately notice whether he has
worked more economically than others or not; if he finds, from reference to the
exchange relations obtaining in the market, that he will not be able to produce
profitably, this shows that others understand how to make a better use of the
goods of higher order in question.</p>
</blockquote>
<p>This is an admission by Mises that he doesn't know how to compute the effects on the economy of using some new productive process.
But as I have shown previously <a href="http://www.härdin.se/blog/2021/02/08/some-example-economic-linear-programs/">here</a>, computing the material effects of new technology is relatively straightforward.
Mises on the other hand must resort to comparing exchange values,
and claims that the result of this is always the best use of resources.</p>
<p>Mises makes the case that all economic activity is in fact exchange (circulation), in stark constrast to the classical economists, especially Marx.
By making circulation central, rather than production, or the combination of production and circulation, Mises again shares traits with the neoclassicals.</p>
<p>Mises does make this very good point:</p>
<blockquote>
<p>No single man can ever master all the possibilities of production, innumerable as they are, as to be in a position to make straightway evident judgments of value without the aid of some system of computation.</p>
</blockquote>
<p>In other words, the sheer number technical coefficients combined with the limitations of the human brain leads to a problem.
To the modern reader there is a simple solution: use computers.</p>
<p>Mises makes a second useful observation: monetary calculations can be dispensed with in household economies.
The reasoning for this is that household economies are small enough that a single human can understand them.
But loyal readers should know that we can offload this process to computers.
This leads to a realization, for which I thank Mises: socialism can be understood as a worldwide household economy!
Planning can be viewed as "householding" (<em>hushålla med</em>, being thrifty with) our limited resources.</p>
<p>Mises also goes into a quaint argument against <em>in natura</em> planning (calculation in kind), stating that it is impossible to compute how much intermediate goods need to be produced in order to arrive at some set of final goods.
This is Mises saying that solving Leontief's <em>(I - A)x = d</em> is impossible, an argument that was invalid even in Mises' day, and one that has been rendered completely moot by modern advances in computing.</p>
<p>One amusing thing about this chapter is that it was written prior to the establishment of <a href="https://en.wikipedia.org/wiki/Gosplan">Gosplan</a> which, despite its many faults, refuted Mises' claim one year later, using <em>pen, paper and mechanical adding machines</em>.
That's not to say that Gosplan was optimal, even by 1920's standards, only that it refuted Mises' notion that planning couldn't work.</p>
<h2>3. Economic Calculation in the Socialist Commonwealth</h2>
<p>Here Mises indirectly makes the point that private enterprises are planned internally, that each branch of an interprise is a household economy.
Mises again claims that exchange is necessary for a rational economy, for economic calculation to take place.
As my readers should now, this is not actually the case.</p>
<p>Mises does raise a good point in this chapter:</p>
<blockquote>
<p>When the “coal syndicate” provides the “iron syndicate” with coal, no price can be formed, except when both syndicates are the owners of the means of production employed in their business. This would not be socialization but workers’ capitalism and syndicalism.</p>
</blockquote>
<p>This is not a uniquely right-wing critique.
The same point is raised by Amadeo Bordiga <a href="https://www.marxists.org/archive/bordiga/works/1957/fundamentals.htm">here</a>, especially in the section <em>The Economic Function</em>:</p>
<blockquote>
<p>To clarify our point, let us imagine that the organisation of bread production, and of all other wheat-based products, is entrusted to the “Bakers’ Union”, with analogous arrangements for all other trades and industries. [...] These organisations would need to make decisions about how to utilise the entire product (in our example: bread, pasta etc,) in such a way as to receive, from other parallel organisations, not only what their members require for their personal consumption, but new raw materials, instruments of labour, etc, as well. Such an economy is an exchange economy.</p>
<p>[At the higher level of the organisation] the system of exchange remains a mercantile one, that is, it requires some law of equivalence in order to equate the value of the stocks of one syndicate with another; and we can easily suppose that these syndicates would be very numerous, and just as easily suppose that each of them would need to separately negotiate with all the others.</p>
<p>[...] Let us be so “liberal” as to think it possible that the various equivalent values could be peacefully determined through a spontaneously arrived at equilibrium. A measuring system of such complexity couldn't operate without the age-old expedient of a general equivalent, in other words, money, the logical measure of every exchange.</p>
</blockquote>
<p>What I want said with these two quotes is that it is impossible to do away with money unless all productive forces fall under the same umbrella, that for economic purposes, they are all part of the one single <em>commune</em>.
If they're not then exchange must be used, and different communes/syndicates/firms/whatever must haggle with each other, production will be haphazard and mediocre and labour and resources will be wasted.
I may go into more detail on this point in a future post,
but in short segmenting the economy in this way means keeping technical coefficients secret,
which can be shown to lead to crises similar to a capitalist economy.</p>
<p>Next Mises makes another incorrect argument around value, stating that two commodities P and Q that both embody 10 hours social labour where P needs two units of raw material a but Q only needs one unit of a, that P is more valuable than Q.
This is the same argument that I replied to using the copper analogy earlier.</p>
<p>Then is another argument about the limited fungibility of labour, which has already been addressed.
For us the fact that some people are adept at different things, that only a certain fraction of the population have the traits necessary to become say a surgeon, is merely another set of constraints to be satisfied.</p>
<p>In the last section of this chapter Mises claims that the labour theory of value is not indispensible to socialism.
This <em>might</em> be true, if unlikely.
Either way this doesn't mean social labour isn't a useful thing to optimize on,
and unlike Mises I claim that we could in fact optimize on anything.
One example of non-labour optimization in planning is the proposal of some technocrats to optimize on energy.
In discussions with local technocrats I've conceded that we could choose to optimize on say a linear combination of labour and energy.
I just happen to believe that minimizing labour is easier to "sell" to people, since most people want more free time.
This is a point I've alluded to in previous posts, most explicitly <a href="http://www.härdin.se/blog/2021/03/04/reducing-emissions-and-saving-lives/">here</a>:</p>
<blockquote>
<p>Once computed, it is in everyone's interest to work according to the plan, since doing so means plan goals are met with a minimum of labour.</p>
</blockquote>
<p>It is also the case that the set of feasible plans is much larger than the set of labour-minimizing or energy-minimizing plans.</p>
<h2>4. Responsibility and Initiative in Communal Concerns</h2>
<p>In this chapter Mises claims that socialists are in favor of a system where workers are renumerated regardless of the amount of social labour performed, something that has never been the case, at least in the Marxist camp.
This passage is an example of this claim:</p>
<blockquote>
<p>The obvious objection that the individual is very little concerned whether he himself is diligent and enthusiastic, and that it is of greater moment to him that everybody else should be, is either completely ignored or is insufficiently dealt with by them. They believe they can construct a socialist commonwealth on the basis of the Categorical Imperative alone.</p>
</blockquote>
<p>Mises is however correct, that merely <em>hoping</em> that people do the right thing, is utopian.</p>
<h2>5. The Most Recent Socialist Doctrines and the Problem of Economic Calculation</h2>
<p>Here Mises points out that the nationalization and amalgamation of all banks into a single central bank,
coupled with abolishing markets,
means that the central bank seizes to be a bank.
This is correct, and this critique is not dissimilar to Marx' critique of the Owenites' labour money.
It also seems that Mises anticipates the <em>ad-hoc</em> nature of Gosplan, which I think is also a fair critique.</p>
<p>Mises also has a bit of fun here poking at Lenin's move towards the <a href="https://en.wikipedia.org/wiki/New_Economic_Policy">New Economic Policy (NEP)</a>.
Mises also points out that Lenin does not properly distinguish between monetary calculation and calculation in kind.
This is also a correct observation, as far as I can tell.</p>
<h2>Conclusion</h2>
<p>In the conclusion Mises reiterates that only private property and exchange can be economically rational.
This supposed rationality stands against the wasteful use of resources in the capitalist mode of production.
Fossil fuel use is again an excellent example,
along with the bourgeois states dragging their feet on the environmental issue.</p>
<p>Mises again returns to exchange as being useful for people to gauge their relative desire for certain goods,
but conveniently ignores that whoever has the most economic muscle has the most to say in exchange relations.
References to petty consumption of alcohol or tobacco ignores the reality of the class system,
the immense autocratic power held by the haute bourgeoisie.</p>
<h2>Postscript: Why a Socialist Economy is “Impossible”</h2>
<p>There is a postscript by <a href="https://en.wikipedia.org/wiki/Joseph_T._Salerno">Joseph T. Salerno</a> in this version of the text.
Among reiterations of the points in the main text, Salerno is upset at <a href="https://en.wikipedia.org/wiki/Friedrich_Hayek">F. A. Hayek</a> for framing Mises' arguments in a way that they may be refuted.</p>
<p>One thing near the end of the postscript stands out in particular:</p>
<blockquote>
<p>This is true, for example, of environmental regulations that prohibit development activities for the vast majority of Alaskan land and along much of the California coastline as well as of recent calls for suppressing development of
Amazon rain forest and coercively maintaining the entire continent of Antarctica forever wild.
Needless to say, thoroughgoing and centralized land use regulations, which some fanatical environmentalists are calling for, is tantamount to the abolition of private property in national resources and business structures.</p>
</blockquote>
<p>Free market apologists like Salerno offer no solution to the environmental question.
They do not suggest any way we might "household" with our limited resources,
any way that we might prevent a runaway greenhouse effect.
Therefore the solution is exactly what Salerno fears: the abolition of private property and the global planning of land use.
To keep free market economics going at this point is at best utopian and childish, and at worse deliberately genocidal.</p>Domain redirects relaxed2021-06-25T23:54:19+02:002021-06-25T23:54:19+02:00tomastag:www.härdin.se,2021-06-25:/blog/2021/06/25/domain-redirects-relaxed/<p>A recent email has revealed to me that insisting on redirecting <em>[www.]haerdin.se</em> to <em>www.härdin.se</em> doesn't work as well as I initially expected.
Because of <a href="https://en.wikipedia.org/wiki/Internationalized_domain_name">IDN rules</a>, despite people copy-pasting links I send them, these links may be presented as <em>www.xn--hrdin-gra.se</em>.
Another potential complication is …</p><p>A recent email has revealed to me that insisting on redirecting <em>[www.]haerdin.se</em> to <em>www.härdin.se</em> doesn't work as well as I initially expected.
Because of <a href="https://en.wikipedia.org/wiki/Internationalized_domain_name">IDN rules</a>, despite people copy-pasting links I send them, these links may be presented as <em>www.xn--hrdin-gra.se</em>.
Another potential complication is that even if <em>härdin.se</em> copy-pastes fine this is not very accessible for people without an ä key or umlaut modifiers on their keyboards.
I have therefore made it so that both <em>www.haerdin.se</em> and <em>www.härdin.se</em> present the same site.
I still have the <a href="https://www.yes-www.org/">yes-www</a> redirects in place,
so <em>haerdin.se</em> redirects to <em>www.haerdin.se</em> and <em>härdin.se</em> to <em>www.härdin.se</em>.</p>
<p>The specific background for this is <a href="https://youtu.be/soDlyercgOo">this video featuring Paul Cockshott</a>,
which has a link to <a href="http://www.härdin.se/blog/2021/02/24/planning-complexity-for-model-economies/">this post</a> with the less-than-pretty <em>xn--hrdin-gra.se</em> domain name.
I actually wasn't aware of this video or this problem until earlier today.</p>
<p>Summary:</p>
<ul>
<li>English speakers may use <em>haerdin.se</em> in place of <em>xn--hrdin-gra.se</em></li>
<li>Swedish speakers may keep using <em>härdin.se</em> as before</li>
</ul>Liquid metal cell2021-05-28T12:33:33+02:002021-05-28T12:33:33+02:00tomastag:www.härdin.se,2021-05-28:/blog/2021/05/28/liquid-metal-cell/<p>The last year or so I've been interested in liquid metal batteries, also known as molten salt batteries.
The idea is to use a molten salt as an electrolyte instead of a water-based electrolyte,
and molten metals for the anode and cathode.
Because of differences in density of the materials …</p><p>The last year or so I've been interested in liquid metal batteries, also known as molten salt batteries.
The idea is to use a molten salt as an electrolyte instead of a water-based electrolyte,
and molten metals for the anode and cathode.
Because of differences in density of the materials, they spontaneously separate into layers.
Also because all three components are molten, these cells should be capable of an unlimited number of cycles.</p>
<p>One downside to this style of battery is the high temperatures necessary.
Magnesium for example melts at 650°C.
This means a lot of insulation is necessary to hold in the heat.
The bigger the cell, the more active material there is relative to the amount of insulation (<a href="https://en.wikipedia.org/wiki/Square-cube_law">square-cube law</a>).
A single cell is likely to weigh several tons.
For this reason liquid metal batteries are best suited for stationary applications, for example grid energy storage.</p>
<h2>Materials</h2>
<p>There is a vast amount of combinations of materials one might use for these kinds of cells.
In the following sections I will summarize what I consider some candidate materials based on wholesale prices found on <a href="https://www.alibaba.com/">alibaba.com</a>.
For many of these materials it is beneficial to form <a href="https://en.wikipedia.org/wiki/Eutectic_system">eutectic mixtures</a>,
thus lowering system temperature.</p>
<h3>Salts</h3>
<p>In the literature halogen salts are the most common electrolytes.
Personally I've experimented with eutectic mixtures of the following (melting points in paretheses):</p>
<ul>
<li>NaCl-KCl (652°C)</li>
<li>NaCl-KCl-CaCl<sub>2</sub> (483°C)</li>
<li>NaCl-KCl-MgCl<sub>2</sub> (382°C)</li>
</ul>
<p>These are all safe and non-toxic.
BaCl<sub>2</sub> is another candidate salt mentioned in the literature, but its toxicity means I avoid it for now.
LiCl is another one which I avoid, but for geopolitical reasons.
Lithium seems to have become a conflict metal.</p>
<h3>Electrode materials</h3>
<p>Reduction potentials (E⁰) are taken from [1] and [2].</p>
<table>
<tr>
<th>Element</th>
<th>Cost (USD/mol)</th>
<th>T<sub>melt</sub> (°C)</th>
<th>E⁰ (V)</th>
</tr>
<tr><td>Sr</td><td>0.552</td><td>777</td><td>-3.684</td></tr>
<tr><td>Ca</td><td>0.064</td><td>842</td><td>-3.534</td></tr>
<tr><td>Na</td><td>0.069</td><td>98</td><td>-3.519</td></tr>
<tr><td>Mg</td><td>0.060</td><td>650</td><td>-2.722</td></tr>
<tr><td>Al</td><td>0.036</td><td>660</td><td>-1.990</td></tr>
<tr><td>Zn</td><td>0.110</td><td>420</td><td>-1,626</td></tr>
<tr><td>Pb</td><td>0.414</td><td>327</td><td>-1,247</td></tr>
<tr><td>Sn</td><td>2.255</td><td>232</td><td>-1,223</td></tr>
<tr><td>Sb</td><td>0.511</td><td>631</td><td>-0,849</td></tr>
<tr><td>Bi</td><td>1.672</td><td>272</td><td>-0,730</td></tr>
<tr><td>Cu</td><td>0.726</td><td>1085</td><td>-0,595</td></tr>
</table>
<h3>Other electrode materials</h3>
<p>It is possible to use non-metals for one or both electrodes.
I have not investigated this, partly because I have not found literature detailing reduction potentials for non-metals in their molten salts.
Sulfur to me is the most interesting candidate of the non-metals, possibly using sulfate salts as electrolyte.
It is however more difficult to work with due to SO<sub>2</sub> fumes.</p>
<h2>Experiments so far</h2>
<p>To test these ideas I have constructed some cells using borosilicate test tubes, heated either by kiln or propane torch.
An example cell is shown below:</p>
<p><a href="http://www.härdin.se/images/lmb/P5282146.JPG"><img alt="Example cell. Glass is visibly cracked, salt leaking out." src="http://www.härdin.se/images/lmb/tP5282146.JPG"></a></p>
<p>The above is a Zn | NaCl-KCl-MgCl<sub>2</sub> | Ca-Mg cell, cracked due to thermal stress.
The white and black part is the cathode, the gray below is the salt and below that is the zinc.
Before the cell cracked I was able to measure a cell voltage of 1.003 V across a 2.2 kΩ load and a short-circuit current of 60.0 mA (23.6 mA/cm²).
Both voltage and current increased as temperature increased, until the cell started cracking enough for the electrolyte to leak out.</p>
<p>I am not sure whether the calcium participates in the cell at all.
If it did I would expect a cell voltage of 1.9 V, whereas Zn||Mg alone should be 1.1 V.
Part of the problem here is that I only have calcium turnings available, whereas the magnesium is powdered.
The magnesium is there only to form a eutectic.
Another problem with this cell is that the calcium quickly oxidizes to CaO, visible as the white stuff in the top of the test tube.</p>
<p>It is possible that I'm not getting the temperature high enough for the cathode to melt correctly.
Rather than setting up a kiln I merely heated the cell in air using the torch, like the arranged photo below:</p>
<p><a href="http://www.härdin.se/images/lmb/P5282145.JPG"><img alt="The earlier cell being heated by a propane torch." src="http://www.härdin.se/images/lmb/tP5282145.JPG"></a></p>
<p>To properly use calcium I would likely have to set up a cell in an inert atmosphere.
This is unfortunately beyond my current means.</p>
<h2>Conclusion</h2>
<p>I have more chemistries to experiment with, and I'm slowly building confidence in my technique.
I will need a logging bench multimeter of some kind to evaluate cells over longer periods of time,
preferably a multimeter that <a href="https://sigrok.org/">sigrok</a> supports.</p>
<p>Finally, this idea is nothing new - there is a company called <a href="https://ambri.com/">Ambri</a> that does exactly this using magnesium as the cathode and an antimony-lead eutectic as the anode (Mg||Sb-Pb).
This is indeed a chemistry that shows up as a possible candidate in my calculations,
but Ca-Mg||Sb-Pb would be superior to it, if an inert atmosphere can be maintained.
For the melting point of Ca-Mg the lead in the anode is redundant, so the cell could be simplified to Ca-Mg||Sb.</p>
<h2>References</h2>
<p>[1] <em>Standard electrode potentials in molten chlorides</em>, H. C. Gaur and H. L. Jindal, Electrochimica Acta, April 1968, vol. 13, issue 4, pp. 835-842, <a href="doi:10.1016/0013-4686(68)85016-9">doi:10.1016/0013-4686(68)85016-9</a>.</p>
<p>[2] <em>Theoretical Electromotive Forces for Cells Containing a Single Solid or Molten Chloride Electrolyte</em>, Walter J. Hamer, Marjorie S. Malmberg and Bernard Rubin, Journal of The Electrochemical Society, January 1956, vol. 103, no. 1, <a href="doi:10.1149/1.2430236">doi:10.1149/1.2430236</a>.</p>Simplified website design2021-05-18T20:32:02+02:002021-05-18T20:32:02+02:00tomastag:www.härdin.se,2021-05-18:/blog/2021/05/18/simplified-website-design/<p>I simplified the CSS on here to hopefully work better for people who are using a dark theme.
I also made the index pages like <a href="http://www.härdin.se/category/blog.html">Blog</a> into tables, which should hopefully work better with screen readers.</p>Verifiable sortition2021-05-01T14:45:00+02:002021-05-01T14:45:00+02:00tomastag:www.härdin.se,2021-05-01:/blog/2021/05/01/verifiable-sortition/<p>In previous posts I have highlighted the role of sortition (selection by lot) as a means of improving democracy.
In this post I will focus on the mathematics of how to arrange systems that are (hopefully) difficult to game.
The first system is computerized while the second system is considerably …</p><p>In previous posts I have highlighted the role of sortition (selection by lot) as a means of improving democracy.
In this post I will focus on the mathematics of how to arrange systems that are (hopefully) difficult to game.
The first system is computerized while the second system is considerably more low-tech, relying mostly on dice rolls.</p>
<p>The are two assumptions necessary to make these systems work: that there exists a list of the people eligible and willing for the sortition, and that each such person appears exactly once on the list.</p>
<p>Call the number of people on the list <em>n</em> and the number of people to choose <em>k</em>.
The number of combinations is <math>
<mrow><mi>M</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mrow><mo stretchy="true">(</mo><mrow><mfrac linethickness="0"><mi>n</mi><mi>k</mi></mfrac></mrow><mo stretchy="true">)</mo></mrow></mrow>
</math> and the total amount of entropy is <math>
<mrow><mi>E</mi><mo lspace="0.278em" rspace="0.278em">=</mo><msub><mi>log</mi><mn>2</mn></msub><mspace width="0.167em"/><mi>M</mi></mrow>
</math>.
To draw for example a body of 1001 seats from 10 billion people requires 24713.1 bits of entropy.
Drawing candidates one-by-one requires somewhat more entropy: <math>
<mrow><msub><mi>log</mi><mn>2</mn></msub><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>n</mi><mo lspace="0" rspace="0">!</mo><mo lspace="0" rspace="0" stretchy="false">/</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>n</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mi>k</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0">!</mo><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> = 33252.5 bits.</p>
<h2>Gathering entropy</h2>
<p>The main problem is gathering the necessary amount of entropy.
Specifically the system must come up with a number <em>N</em> between <em>0</em> and <math>
<mrow><mrow><mo stretchy="true">(</mo><mrow><mfrac linethickness="0"><mi>n</mi><mi>k</mi></mfrac></mrow><mo stretchy="true">)</mo></mrow><mo lspace="0.222em" rspace="0.222em">-</mo><mn>1</mn></mrow>
</math> in a way that is not biased.
Luckily this is quite straightforward:
combine entropy from multiple sources using modular addition.
As long as at least one entropy source is unbiased then the resulting number will also be unbiased.
Participants must also be prevented from seeing the other submissions.</p>
<p>When the sortition happens, the process should be broadcast to encourage public scrutiny.
Various groups should take part in the process, each coming up with their own <em>N</em> and submitting it to the system within say a day.
Universities and schools could be involved, or just any body of people concerned with the democratic process.
Each <em>N</em> should then be encrypted, thus "sealing" them, and submitted to some central server.
After some time, say a day, decryption keys should be provided, with a deadline of say one week.
Submissions that don't meet the deadline are discarded.
Things should be arranged so that anyone can download the relevant files and re-run the sortition program, thus verifying the results.</p>
<p>Further inspiration can be had from <a href="https://www.iana.org/dnssec/ceremonies">ICANN's key signing ceremonies</a>.</p>
<h2>Computing winners</h2>
<p>The act of turning <em>N</em> into an assignment of seats in the body is a combinatorial operation known as <em>unranking</em>.
Wikipedia's article on <a href="https://en.wikipedia.org/wiki/Combinatorial_number_system">combinatorial number systems</a> describes an overview of the process.
Each <math>
<msub><mi>c</mi><mi>i</mi></msub>
</math> can be found by binary search.
This means evaluating <math>
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>k</mi><mspace width="0.167em"/><mi>log</mi><mspace width="0.167em"/><mi>n</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> binomial coefficients, each one no larger than <em>M</em>.
Each coefficient takes no longer than <math>
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msup><mi>k</mi><mn>2</mn></msup><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>log</mi><mspace width="0.167em"/><mi>n</mi><msup><mo lspace="0" rspace="0" stretchy="false">)</mo><mn>2</mn></msup><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> time to compute, using long multiplication.
Thus the entire process takes at most <math>
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msup><mi>k</mi><mn>3</mn></msup><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>log</mi><mspace width="0.167em"/><mi>n</mi><msup><mo lspace="0" rspace="0" stretchy="false">)</mo><mn>3</mn></msup><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">=</mo><mover><mi>O</mi><mo stretchy="false" accent="true">˜</mo></mover><mo lspace="0" rspace="0" stretchy="false">(</mo><msup><mi>k</mi><mn>3</mn></msup><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> time.
With FFT multiplication the bound shrinks to <math>
<mrow><mover><mi>O</mi><mo stretchy="false" accent="true">˜</mo></mover><mo lspace="0" rspace="0" stretchy="false">(</mo><msup><mi>k</mi><mn>2</mn></msup><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math>.</p>
<h2>Lower-tech methods</h2>
<p>The method described above may be too high-tech to count as sufficiently scrutable.
The simplest method is likely printing paper slips of every person on the list of candidates and drawing them out of a hat on live TV.
This suffers from the risk of some names not having been printed.
There is also that if each slip is the size of a grain of rice then the hat must have a volume of 750 m³.</p>
<p>Another way is rolling dice.
Picking candidates from a pool of 10,000,000,000 using 6-sided dice (d6) requires <math>
<mrow><mo lspace="0" rspace="0" stretchy="false">⌈</mo><msub><mi>log</mi><mn>6</mn></msub><mspace width="0.167em"/><msup><mn>10</mn><mn>10</mn></msup><mo lspace="0" rspace="0.278em" stretchy="false">⌉</mo><mo lspace="0" rspace="0.278em">=</mo><mn>13</mn></mrow>
</math> rolls each, or 5 rolls if using d100's.
Using d10's or d100's has the benefit of being easier to understand compared to working in base-6.
This is more dice rolls than necessary for computing <em>N</em>, 5005 rolls vs 2730 rolls if using d100's.
Once selected, each candidate is stricken off the list.</p>
<p>Some care needs to be taken how to convert the generated numbers into candidates, to avoid bias.
First the result of each d100 should be reduced mod 100.
The result of 5 rolls is a number between 0 and 9,999,999,999.
If there are 9,876,543,210 candidates then values between 9,876,543,210 and 9,999,999,999 means another roll needs to be performed, yielding a number between 9,876,543,210 and 999,999,999,999.
Of these only values between 997,530,864,211 and 999,999,999,999 cannot be reduced mod 9,876,543,210 without bias.
This process terminates quickly with high likelyhood,
and only requires basic knowledge of modular arithmetic to understand.
If a candidate that has already been selected is selected in this process then another dice can simply be rolled.</p>
<p>Every candidate can watch/listen to the proceedings via TV, their number in the lot being printed on their "ballot" and verifiable by what's going on in the broadcast.
This could be an excellent opportunity to bring on mathematics communicators like <a href="https://en.wikipedia.org/wiki/Matt_Parker">Matt Parker</a>, to make the whole thing more interesting.
Printed tables can be prepared in advance to assist in the necessary long divisions, including upper limits for when extra rolls are necessary.
Performing the computations by hand should instill more confidence in the results,
computers only being used to verify the calculations.</p>
<p>An even simpler method would be to re-roll all dice until a number less than <em>n</em> is arrived at.
Note that it is not sufficient to re-roll only dice that cause the result to be greater than or equal to <em>n</em>.
Doing so introduces a bias.
All dice must be re-rolled.
For example if <em>n</em> is 9801 then for the first die only numbers in the range 0-98 would be accepted.
This heavily biases the result towards the lot with number 9800 because that is the only one that starts with 98.
This means lot #9800 has probability 1/99 whereas lots #0000 to #9799 each only have probability 1/9900.</p>
<h2>Then what?</h2>
<p>Selecting what set of candidates should make up a body is only part of the problem.
How should this new set of people actually be integrated into the body?
Should there be overlapping sortitions so that only part of the body is replaced at a time?
Should there be mandatory education as part of the process, to learn the ropes?
These things may likely be different depending on the responsibilities of the body.
Local bodies may have lower requirements than say one that decides on questions that are of global concern.</p>ZVS induction heater2021-04-24T18:21:21+02:002021-04-24T18:21:21+02:00tomastag:www.härdin.se,2021-04-24:/blog/2021/04/24/zvs-induction-heater/<p><em>Update</em>: see the bottom of the post.</p>
<p>In the last few days I've built myself an induction heater.
This is part of some high-temperature electrochemistry I'm doing as a side project.
I was tired of burning through nichrome wire for my mini-furnace, so I decided to give inductive heating a …</p><p><em>Update</em>: see the bottom of the post.</p>
<p>In the last few days I've built myself an induction heater.
This is part of some high-temperature electrochemistry I'm doing as a side project.
I was tired of burning through nichrome wire for my mini-furnace, so I decided to give inductive heating a try.
Below is a picture of the setup I currently have:</p>
<p><a href="http://www.härdin.se/images/zvs/P4222128.JPG"><img alt="Picture of the setup. Glowing iron wire is visible." src="http://www.härdin.se/images/zvs/tP4222128.JPG"></a></p>
<p>85 W is being dumped into the iron wire in the work coil, causing the iron to glow red hot.
Choke and capacitor temperatures are monitored with thermocouples.
Unloaded tank voltage is 27 V<sub>RMS</sub>, around 11 V<sub>RMS</sub> loaded.
The circuit is a typical Mazzilli-style zero voltage switch (ZVS) driver and is shown below:</p>
<p><img alt="Circuit." src="http://www.härdin.se/images/zvs/zvs.png"></p>
<p>Both 1N4148's and 1N4007's are used to try and make the gate switching as fast as possible.
High-current traces must be beefed up by adding extra copper and solder, as shown in the photo below:</p>
<p><a href="http://www.härdin.se/images/zvs/P4222131.JPG"><img alt="Bottom of board." src="http://www.härdin.se/images/zvs/tP4222131.JPG"></a></p>
<p>The LC tank is especially important, as it operates at around 50 kHz, meaning a <a href="https://en.wikipedia.org/wiki/Skin_effect">skin depth</a> of 300 µm.
If this isn't done then the traces may easily overheat and start burning the underlying FR-4 substrate.
Thickening the traces also improves the tank's <a href="https://en.wikipedia.org/wiki/Q_factor">Q</a>, increasing efficiency.</p>
<p>A top-down shot is provided below:</p>
<p><a href="http://www.härdin.se/images/zvs/P4222129.JPG"><img alt="Top-down view." src="http://www.härdin.se/images/zvs/tP4222129.JPG"></a></p>
<p>C1 and C2 have some aluminium tape attached to try and help with cooling.
L1 is 8 turns of 6 mm copper tubing wound around a 35 mm steel bar as a former.
L2 and L3 are 4 m of insulated wire wound on T130-2 toroids, a bit over 100 µH.
Q1 and Q2 are some random N-channel MOSFETs I had laying around.</p>
<p>I don't yet have a power supply set up capable of delivering enough current to fully drive this thing.
Before I do that I have some ideas for improvements:</p>
<ul>
<li>
<p>reduce length, increase thickness of wire on chokes. Simulations show 3 µH may be enough. Litz wire and larger cores are further methods</p>
</li>
<li>
<p>use lower ESR capacitors, for example <a href="https://www.digikey.com/en/products/detail/kemet/R76MW468050H3J/10428775">R76MW468050H3J</a> or <a href="https://www.digikey.com/en/products/detail/illinois-capacitor/505LC3400K5LM8/6051342">505LC3400K5LM8</a></p>
</li>
<li>
<p>use a more application-suitable work coil. Smaller diameter and more turns, possibly using 2 mm magnet wire</p>
</li>
<li>
<p>bring frequency down to around 10 kHz to help with skin depth issues</p>
</li>
<li>
<p>add around 100 µF to the supply before the chokes</p>
</li>
</ul>
<h2>Updates</h2>
<h3>2021-04-25</h3>
<p>Rewound the chokes using some home-made Litz wire. 30 strands 0.2 mm diameter, 2 meters per core. Measures at 16 µH. Significantly less heat, not much change in RMS voltage.</p>
<p>I also added 1 mF of input capacitance, which boosted the output voltage to 57 V<sub>RMS</sub> or so without load.
This seems to have been enough to destroy at least one of the MOSFETs, since the BUK9518-55A is only rated for 55 V.</p>
<p>The MOSFETs were switched to a pair of IRF520's which have higher voltage rating but also a higher R<sub>DS(on)</sub>, going from 12 mΩ to 270 mΩ.
This results in much higher losses to where the heatsinks become noticably hot within a few seconds.
The IRF520 has lower total gate charge and input capacitance, so the losses are not due to the transistors switching more slowly.
Switch-on time should be around 200 ns, much lower than the cycle time of 20 µs.</p>
<p>Some 22 V Zeners were also added to the MOSFET gates to protect them. This is a few volts higher than what the datasheet says is the maximum allowable gate voltage, but it is what I have on hand.</p>Building the cybernetic commune2021-04-15T23:06:40+01:002021-04-15T23:06:40+01:00tomastag:www.härdin.se,2021-04-15:/blog/2021/04/15/building-the-cybernetic-commune/<p>In this post I will propose some bottom-up strategies for establishing a global cybernetic commune.
I believe these ideas are quite distinct from both the anarchist and Marxist-Leninist traditions,
hence why I'm writing this post to hopefully get constructive criticism so these ideas can be developed further.</p>
<h2>The bottom-up case …</h2><p>In this post I will propose some bottom-up strategies for establishing a global cybernetic commune.
I believe these ideas are quite distinct from both the anarchist and Marxist-Leninist traditions,
hence why I'm writing this post to hopefully get constructive criticism so these ideas can be developed further.</p>
<h2>The bottom-up case</h2>
<p>The case for a bottom-up approach is that it is difficult to
experiment with different forms of planning and democracy under duress.
A system born in peace time has more time to work out both of these things properly.
The idea is to have the system grow in a viral fashion at a moderate pace.
A sort of "cold" revolution rather than the violent "hot" revolutions we often see historically.
I suspect these ideas are useful also in dire circumstances.</p>
<p>In its initial stages, the system consists of isolated pockets connected by planning and a political structure.
These pockets can reside anywhere in the world.
As the system grows, the pockets merge, creating greater and greater cells.
The end goal is that the entire world economy is connected to the system.
This is necessary in order to be able to deal with the environmental challenge,
and to be able to deal with fossil fuel states like Norway and Germany.
Or in Marx' terms, to deal with the anarchy of production.</p>
<p>The reason that I think this strategy can work is due to the rising popularity of worker co-ops.
While cooperatives are generally associated with market "socialist" ideas,
and econophysics tells us market socialism is ultimately unworkable,
co-ops slot quite nicely into a cybernetic planning system.
That way co-ops don't need to compete with each other - instead they can share resources and
perform all sorts of internal accounting tricks without involving the market.
This should result in a kind of "comedy of the commons" effect -
the more workplaces that connect to the system, the more everyone in the system benefits.
I see similar effects in the free software world.</p>
<h2>Bootstrapping</h2>
<p><a href="https://en.wikipedia.org/wiki/Autarky">Autarky</a> is the situation where an economy is self-reliant.
As the goal is incorporating the entire world economy,
at some point autarky must be achieved.
This means to be able to produce all essential goods from scratch, to have functioning
healthcare, schools, waste management, elderly care etc.
Once the system is in a position of autarky it is self-justifying.
It is also free to pursue its goals more aggresively.</p>
<p>Autarky is very similar in concept to <a href="https://en.wikipedia.org/wiki/Bootstrapping">bootstrapping</a>.
A bootstrapped system is one that is able to reproduce itself.
Once bootstrapped, the commune has responsibility primarily to itself.</p>
<h2>Tit-for-tat</h2>
<p>At some point there will come a time when the authorities in the various host states will start
noticing the communards in their midst.
It is at this point that it will become apparent whether these states and their functionaries
are friendly or hostile.
This may not be immediately obvious, and it may be necessary for the commune to perform a bit of
intelligence gathering, PR, lobbying and so on.
So long as the state does not aggrieve then all is good.
But should the state choose to be hostile, then the commune must be prepared to defend itself.
Once hostilities seize, then the commune should also be conciliatory.
In game theory this is known as the <a href="https://en.wikipedia.org/wiki/Tit-for-tat">tit-for-tat strategy</a>,
which is known to be highly effective.</p>
<p>Another reason why friendly relations are useful is because eventually much of the functionality
of the extant states will be rolled into the commune itself.
Therefore it makes sense not to needlessly antagonize the people employed in the various departments of each state.</p>
<h2>Law</h2>
<p>The commune will inevitably need a justice system to handle internal affairs.
I can't say too much on the subject of law since it is not my area,
but it is important that outside forces be prevented from interfering in the commune's affairs.
For example if the commune decides to evict members that engage in actions counter to
the goals of the commune, it should not be possible for such former members to then sue the
commune.
If former members better themselves then they should be let back in, in line with tit-for-tat.</p>
<p>A recent example of what can happen if outside interference is allowed is here in Sweden where
<a href="https://www.transport.se/">Transportarbetareförbundet</a> has been
<a href="https://www.svt.se/nyheter/lokalt/norrbotten/fackforbund-uteslot-sd-politiker-i-kiruna-nu-avgors-tvisten-i-domstol">sanctioned for excluding members active in SD, our largest reactionary political party</a>.
The fact that our unions must bend the knee to the state in this manner is indicative of weakness.</p>
<h2>Taxes</h2>
<p>Every society capable of reproducing itself needs to support its non-working and less-working members.
This includes children, the sick, the elderly, people with certain disabilities and so on.
This is one of the functions of the tax system, at least here in Sweden.
Since the goal is autarky, so too must the commune have its own "tax" system.
The exact shape of such a system is a whole series of posts unto itself,
as is the entire problem of remuneration, which ties into the entire debate about value.
But I'll make this observation:</p>
<p>Taxes may be used to encourage work in less attractive or dangerous fields like sewage or deep-sea welding,
by increasing remuneration for work in these fields.
Such increases would need to be funded by the tax system.
The end result of high remuneration for unpleasant or dangerous work
is that workers in those fields need to work less than average.</p>
<p>How much of a surplus that should be produced for this "tax" system,
and how it should be distributed,
is something that could be decided for example through annual plebiscite.
Which brings us to the next and last section.</p>
<h2>Democracy</h2>
<p>When it comes to democracy I have for quite a few years toyed with the idea of simply drawing representatives by lot.
The reason for doing this is to get rid of political parties,
and because it is a straightforward way to represent the masses.
The last point can be argued from statistics.</p>
<p>I was pleasantly surprised to learn quite recently that this is an old idea,
most notably practiced by <a href="https://www.worldhistory.org/Athenian_Democracy/">the ancient Athenians</a>.
Cockshott & Cottrell also propose a system like this.
I would add that it is important that the system be opt-out,
meaning everyone is part of the draw by default.</p>
<p>I realize there are many practical problems with this style of democracy.
Perhaps a kind of multi-house solution would work better,
where one house is drawn by lot,
another is composed of experts
and a third house holds representatives of certain minorities that require special representation.
This is part of the reason why I started this series of posts saying that I can't get into how exactly policies are decided upon,
since I simply don't know what will work best.
Whatever the political constellation, it must be in line with science
and it must be able to overcome the anarchy of production,
or else the future of our species will be barbarism.</p>Certbot, hidden service fixed2021-03-14T17:47:47+01:002021-03-14T17:47:47+01:00tomastag:www.härdin.se,2021-03-14:/blog/2021/03/14/certbot-hidden-service-fixed/<p>The web server has been unstable for the last week or so.
This issue was traced to a combination of using Apache 2.2 and a needlessly complicated certbot setup.
The latter would lead to apache2 shutting down seemingly at random whenever certain certificates were updated.
For anyone else that …</p><p>The web server has been unstable for the last week or so.
This issue was traced to a combination of using Apache 2.2 and a needlessly complicated certbot setup.
The latter would lead to apache2 shutting down seemingly at random whenever certain certificates were updated.
For anyone else that has this problem and stumbling on this post, the solution is to edit the <code>[renewalparams]</code> section in <code>/etc/letsencrypt/renewal/*.conf</code> so that it looks something like this:</p>
<div class="highlight"><pre><span></span><code><span class="err">#</span><span class="w"> </span><span class="n">Options</span><span class="w"> </span><span class="n">used</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">renewal</span><span class="w"> </span><span class="n">process</span>
<span class="o">[</span><span class="n">renewalparams</span><span class="o">]</span>
<span class="n">account</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">xxx</span>
<span class="n">authenticator</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">apache</span>
<span class="n">installer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">apache</span>
<span class="n">server</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">xxx</span>
</code></pre></div>
<p>The important bit is that <code>authenticator</code> and <code>installer</code> are both set to <code>apache</code> and that there are no hooks in there that mess with the apache2 service.</p>
<p>I have also set up <a href="https://github.com/afollestad/nock-nock">Nock Nock</a> on my phone to notify me if somehow the website goes down again.</p>
<h2>Hidden service changed to v3</h2>
<p>The Tor hidden service has changed address from xynphzf7j7newda6.onion to <a href="http://pfcgmo5hwfffwhis3zty2u2ufryrnzypue34h74va6ykw5iazgcvvtqd.onion/">pfcgmo5hwfffwhis3zty2u2ufryrnzypue34h74va6ykw5iazgcvvtqd.onion</a>.
This is due to v2 addresses being deprecated and the tor service refusing to advertise them.</p>The five second plan2021-03-13T20:58:00+01:002021-03-13T20:58:00+01:00tomastag:www.härdin.se,2021-03-13:/blog/2021/03/13/the-five-second-plan/<p>In the previous posts in this series I've made the argument that using linear programming to do planning is much more feasible than previously thought.
In this post I will look at how we might deal with changing circumstances and how the plan might be adjusted to account for them …</p><p>In the previous posts in this series I've made the argument that using linear programming to do planning is much more feasible than previously thought.
In this post I will look at how we might deal with changing circumstances and how the plan might be adjusted to account for them.</p>
<h2>Disturbances and stability</h2>
<p>As we all know, things tend to never to go entirely according to plan.
Whether it's a hobby project or the operation of a firm or the whole of humanity, there are inevitably unforseen events.
In planning we can simulate what happens to the system if for example a rail line goes down, if there's a drought in some area or if a harvest is surprisingly bountiful.
A well-behaved system should recover from such disturbances in a reasonable amount of time.</p>
<p>At least two sorts of disturbances are of interest: impulses and cyclical disturbances.
For an entirely linear system the <a href="https://en.wikipedia.org/wiki/Impulse_response">impulse response</a> is quite easy to compute.
The shape of the response is also independent of the scale of the impulse.
But as I have pointed out earlier in these posts, real economies are non-linear.
This means that while a small disturbance may be no problem, once it gets beyond a certain threshold, problems associated with it will compound.
Knowing where these thresholds lie is useful for managing risk.</p>
<p>As for cyclical disturbances, we want that they can't bring the system into oscillation.
We want no eigenfrequencies with eigenvalues whose real part is near or above unity.
Here <a href="https://en.wikipedia.org/wiki/Power_iteration">power iteration</a> can be used to compute the largest eigenvalue,
from which stability can be determined.
This again gets trickier when non-linear effects are taken into account, but still it can in principle be computed and planned for.</p>
<p>Capitalism by comparison is notoriously bad at dealing with sudden crises, for example the ongoing COVID-19 situation.
It also suffers from cyclical crashes, which suggests an eigenmode with a period of around a decade.
The greenhouse gas situation, which gets worse at an exponential rate, is evidence of an eigenvalue whose real part is greater than unity.
If we consider capitalism as a control system, it is clearly not doing a good job.</p>
<h2>How often do things change?</h2>
<p>Here I will again gesture towards <a href="https://arxiv.org/pdf/2005.01539.pdf">this work</a> by Spyridon Samothrakis.</p>
<p>We have two pieces of information that we keep track of: the state vector <em>s</em> which tells us how much capital stocks we have and in which locations these stocks are, and the non-linear matrix of technical coefficients <em>F(x,t)</em>.
I have inserted <em>t</em> for the time dimension, but it should be noted that the plan itself can't change unless there is a change in information.
The activation vector <em>x(t)</em> will change over time, for example due to the seasons, since <em>x(t)</em> derives from <em>s</em> and <em>F(x,t)</em>.</p>
<p>We should adjust the plan whenever <em>s</em> or <em>F(x,t)</em> changes.
When goods leave a workplace to be transported elsewhere this amounts to a change in <em>s</em>,
and similarly when the goods arrive at their destination.
Whenever a new factory is constructed, a plot of land is prepared for cultivation or a building burns down, <em>F(x,t)</em> changes.
The sooner the plan can be updated to account for such changes in reality, the more robust the system will be.</p>
<p>To answer the question in the heading, things can change arbitrarily often, especially automated systems.
One example of a subsystem that needs accurate and timely information is the electrical grid.
Since production of for example aluminium comes out of the planning process, so too does the demand for electricity.
As a consequence a properly planned grid has less need for things like current limiting reactors, flywheels, batteries and other load balancing devices.</p>
<h2>Failure is an option</h2>
<p>For the planning system to do its job, it must have accurate information about reality.
It is important that people are not pressured into lying to the system, or into performing shoddy work to fill production quotas.
The system should have a notion of uncertainty when it comes to the data being presented to it.
To err is human after all.</p>
<p>When a problem is discovered and the system is notified of this, it can plan around the problem until it is resolved.</p>
<h2>How fast can we recompute the plan?</h2>
<p>The speed at which the plan can be recomputed depends on how many things have changed, for example how many constraints that will switch from being inactive to active.
It also depends on the granularity of the system, both in space and time.
The near future might be discretized into city blocks and hours. The further into the future we get, the coarser the discretization.</p>
<p>If the changes are small, and we have an approximate solution that is some distance away from the closest constraint, then it is likely that updating the constraints still maintains a feasible solution.
A few centering steps will likely be necessary, but not nearly as many as for finding the initial solution.
We hope that the amount of necessary labour shrinks as a result, which should be the case for any non-disastrous change.</p>
<p>I cannot at the moment say exactly how difficult it is to update the plan, except that it will be much easier than computing the initial solution.
What I suspect will happen is that the system runs continuously, refining the plan as new data comes in.
As people and subsystems look for things to do, the system always presents the latest feasible solution.</p>
<h2>Practical considerations</h2>
<p>Now that we know that adjusting the plan is feasible, we ask ourselves "what does this mean for the worker on the ground"?
After all, if everyone is told to change what they're doing every five seconds, that would quickly get annoying.
To the planning system this means that there is some amount of "human inertia" that has to be accounted for, and new plans can probably not be issued more often than twice per day, to humans at least.
This means that we might have, at most, a "morning plan" and an "after lunch plan".
Automated systems on the other hand will be able to adjust to changing plans more rapidly.</p>Reducing emissions and saving lives2021-03-04T16:03:04+01:002021-03-04T16:03:04+01:00tomastag:www.härdin.se,2021-03-04:/blog/2021/03/04/reducing-emissions-and-saving-lives/<p>In this post I will look at food production and distribution under capitalism and its problems,
and how a cybernetic planned economy might address both.</p>
<h2>Food production under capitalism</h2>
<p>Food production as it is done currently suffers from two major problems: overproduction and greenhouse gas (GHG) emissions.</p>
<p>Food waste varies …</p><p>In this post I will look at food production and distribution under capitalism and its problems,
and how a cybernetic planned economy might address both.</p>
<h2>Food production under capitalism</h2>
<p>Food production as it is done currently suffers from two major problems: overproduction and greenhouse gas (GHG) emissions.</p>
<p>Food waste varies somewhat between countries, but the global average seems to be between 30-50% (<a href="https://en.wikipedia.org/wiki/Food_waste">1</a>, <a href="https://www.usda.gov/foodlossandwaste/why">2</a>).
If we take the number 33% then this means that workers in the food sector work 50% more than what is actually necessary.
If food production were optimized then the working week for food workers could shrink from 40 hours to 30 hours or even 20 hours.
This doesn't happen currently because it is more profitable to let food go to waste.</p>
<p>Food production also accounts for between 24-26% of greenhouse gas (GHG) emissions (<a href="https://ourworldindata.org/food-ghg-emissions">1</a>, <a href="https://www.epa.gov/ghgemissions/global-greenhouse-gas-emissions-data">2</a>).
Since part of these emissions is purely waste, there is room for improvement even without anyone having to change their diet.</p>
<h2>Food distribution under capitalism</h2>
<p>Currently between 9-36 million people die due to starvation every year, depending on how you count (<a href="https://borgenproject.org/how-many-people-die-from-hunger-each-year/">1</a>, <a href="https://www.theworldcounts.com/challenges/people-and-poverty/hunger-and-obesity/how-many-people-die-from-hunger-each-year/story">2</a>).
This is not because we're not producing enough food, clearly, but because the food that is being produced is not getting to the people that need it.
Beyond starvation, around 800 million people are malnourished, one ninth of the world population.
The amount of suffering this entails is hard to fathom.
From a purely economic perspective it is an enormous waste of labour and talent.
Starving bodies means brains and muscles not working as they should.
The labour that goes into raising children and adults, only for them to starve to death, is clearly an immense waste.
Again, this loss of life is not because we don't have enough food, but because people cannot afford it.</p>
<p>The food situation has recently gotten worse due to the COVID-19 pandemic, with an estimated 6,000-12,000 extra deaths per day (2-4 million per year, <a href="https://www.oxfamamerica.org/explore/research-publications/hunger-virus-how-covid-19-fueling-hunger-hungry-world/">1</a>).
These numbers are also bound to get worse as the climate crisis evolves.</p>
<h2>How we could do better</h2>
<p>I should hopefully have made it clear in these posts that one important mechanism in cybernetic planning is constraints.
Constraints allow us to learn whether a proposed plan is feasible or not.
Once computed, it is in everyone's interest to work according to the plan, since doing so means plan goals are met with a minimum of labour.
I will note here that the plan may well change from day to day, depending on how work is progressing and on the amount of computational resources available.</p>
<p>Food is a rather thankful good to plan for, since we know how much of it is necessary in any geographical location based to how many people live there.
People have preferences of course, and these preferences vary by location, but a basic requirement is that people shouldn't starve.
Only after this is ensured can we worry about having more varied diets.</p>
<p>I have <a href="http://www.härdin.se/blog/2021/02/08/some-example-economic-linear-programs/">previously shown</a> that meeting basic macronutritional needs is relatively straightforward.
There is also clearly enough food being produced to maintain a surplus in case of bad harvests or disaster.
We have two problems to solve: distribution and GHG emissions.</p>
<h2>Planning distribution</h2>
<p>Distribution is a productive process where a set of goods is transformed from being in location A to being in location B.
A and B might not be directly linked, so distribution will entail intermediate stops at more locations.
This amounts to solving a <a href="https://en.wikipedia.org/wiki/Multi-commodity_flow_problem">multi-commodity flow problem</a>,
something which we have become quite good at as a species in recent years.
Conveniently, flow problems can be formulated as linear programs and therefore can be plugged in to the same sort of equations as I have elaborated on in these posts.
The problem then becomes knowing how much volume and mass each type of food occupies, how long before it spoils, how fast each mode of transportation is etc.
Ensuring that everyone has enough food therefore means knowing that a feasible solution to the linear program exists, and that this solution is followed by everyone, at least roughly.</p>
<h2>Planning GHG reduction</h2>
<p>As I hinted at in the start of this post, one straightforward way to reduce GHG emissions is by ensuring only as much food as is actually necessary is produced.
Since we know how much food people need, their preferences and how much we have in reserve, we can compute every year how much food should be produced.
There is no need to produce more than this, because reserves have already been planned for.
Based on the numbers presented earlier, potential GHG reductions can be estimated as follows:</p>
<ul>
<li>assume the 1/9 of the world population that currently goes hungry is currently getting zero food (increase demand by 1/8th)</li>
<li>assume that only 30% of food is wasted</li>
<li>assume that agriculture accounts for only 24% of GHG emissions</li>
</ul>
<p>Putting all this together we can expect a reduction of <math>
<mrow><mn>24</mn><mo lspace="0" rspace="0.222em">%</mo><mo lspace="0" rspace="0.222em">*</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0.222em" rspace="0.222em">-</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0.222em" rspace="0.222em">-</mo><mn>0</mn><mo lspace="0" rspace="0">.</mo><mn>3</mn><mo lspace="0" rspace="0.222em" stretchy="false">)</mo><mo lspace="0" rspace="0.222em">*</mo><mn>9</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>8</mn><mo lspace="0" rspace="0.278em" stretchy="false">)</mo><mo lspace="0" rspace="0.278em">=</mo><mn>5</mn><mo lspace="0" rspace="0">.</mo><mn>1</mn><mo lspace="0" rspace="0">%</mo></mrow>
</math>.
In addition, the work week in the food sector would shrink to <math>
<mrow><mn>40</mn><mo lspace="0.222em" rspace="0.222em">*</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0.222em" rspace="0.222em">-</mo><mn>0</mn><mo lspace="0" rspace="0">.</mo><mn>3</mn><mo lspace="0" rspace="0.222em" stretchy="false">)</mo><mo lspace="0" rspace="0.222em">*</mo><mn>9</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mn>8</mn><mo lspace="0.278em" rspace="0.278em">=</mo><mn>31</mn><mo lspace="0" rspace="0">.</mo><mn>5</mn></mrow>
</math> hours.</p>
<h3>Dietary changes</h3>
<p>So far I have assumed that no changes are made in people's diets.
But as most of us know, meat production, especially beef, accounts for a huge amount of emissions (<a href="https://en.wikipedia.org/wiki/Greenhouse_gas#Anthropogenic_greenhouse_gases">1</a>).
Even greater GHG reductions can be had by regarding meat as a luxury rather than a staple as it is now.
It is not unreasonable to enact a rationing system for meat, like many nations do in wartime.
Unlike current attempts like <a href="https://en.wikipedia.org/wiki/Emissions_trading">cap and trade</a>,
where the burden of GHG reduction ultimately falls to the consumer (the working class),
a rationing system would be fair, since it affects everyone equally (except of course vegetarians and vegans).</p>
<p>Stopping meat production entirely would work even better, but is likely politically impossible.
In such a situation, hunting, which is necessary, would be the only source of meat.</p>
<h2>Summary</h2>
<p>9-36 million lives can be saved, 800 million do not need to go hungry, food's work week can be shortened to 32 hours, and a 5% reduction in GHG emissions is possible.</p>Planning complexity for model economies2021-02-24T23:56:00+01:002021-02-24T23:56:00+01:00tomastag:www.härdin.se,2021-02-24:/blog/2021/02/24/planning-complexity-for-model-economies/<p>In this post I will present two model economies that should be useful for anyone who wants to get into planning.
The economies are formulated as linear programs, and the goal is to find optimal solutions to these programs.
I will also provide a sketch for an interior point algorithm …</p><p>In this post I will present two model economies that should be useful for anyone who wants to get into planning.
The economies are formulated as linear programs, and the goal is to find optimal solutions to these programs.
I will also provide a sketch for an interior point algorithm, mostly lifted from existing literature.
Finally I have a few words on how to solve LPs of this type in a distributed manner.</p>
<h2>The models</h2>
<p>The model economies presented here exploit a few notions:</p>
<ul>
<li>in real economies, firms only depend on a finite set of other firms much smaller than the economy as a whole</li>
<li>the average number of firms any one firm depends on is bounded by some constant <math>
<mi>q</mi>
</math> regardless of the size of the economy</li>
<li>the economy has a small set of core industries and a larger "long tail" of less crucial industries</li>
<li>core industries have lots of industries that depend on them, whereas the rest do not</li>
</ul>
<p>There are three components to the models:</p>
<ul>
<li>technical coefficients</li>
<li>a number of extra "basket" constraints</li>
<li>balance equations to enable optimization</li>
</ul>
<p>The difference between the models is the structure of the technical coefficient matrices.
Five parameters determine the size and density of the resulting system matrix <math>
<mi>S</mi>
</math>:</p>
<ul>
<li><math>
<mi>v</mi>
</math> the number of industries</li>
<li><math>
<mi>q</mi>
</math> the number of inputs to each industry, as described earlier</li>
<li><math>
<mi>w</mi>
</math> the number of basket constraints</li>
<li><math>
<mi>r</mi>
</math> the density of each basket constraint</li>
<li><math>
<mi>o</mi>
</math> the number of balance equations to optimize over</li>
</ul>
<p>The technical coefficients are of the same sort as those used by Leontief.
They are arranged so that columns contain the inputs of each firm, and rows correspond to outputs.
The diagonal is the identity matrix. Off-diagonal elements are negative.
The coefficient matrix must satisfy the <a href="https://en.wikipedia.org/wiki/Hawkins-Simon_condition">Hawkins–Simon (HS) condition</a>.
Both matrices are generated through a <a href="https://en.wikipedia.org/wiki/Preferential_attachment">preferential attachment process</a>, and the process used is the difference between the two models. More on that later.</p>
<p>The right-hand side for the technical coefficients are a given list of demands.
Leontief's formulation <math>
<mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>I</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mi>A</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>x</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mi>d</mi></mrow>
</math> is relaxed to <math>
<mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>I</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mi>A</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mi>x</mi><mo lspace="0.278em" rspace="0.278em">≥</mo><mi>d</mi></mrow>
</math>.</p>
<p>The "baskets" are an additional set of constraints.
They allow having multiple technologies available for producing a single good, or a class of goods.
They take the form <math>
<mrow><mi>B</mi><mspace width="0"/><mi>x</mi><mo lspace="0.278em" rspace="0.278em">≥</mo><mi>f</mi></mrow>
</math>, where both <math>
<mi>B</mi>
</math> and <math>
<mi>f</mi>
</math> are non-negative.
We can imagine any number of these extra constraints.
A concrete example would be the nutrition constraints in <a href="http://www.härdin.se/blog/2021/02/08/some-example-economic-linear-programs/">the last post</a>.</p>
<p>The name "basket" comes from something I read about how <a href="https://en.wikipedia.org/wiki/Gosplan">Gosplan</a> worked.
Due to limited computational resources Gosplan could not plan things using disaggregated data.
Instead they had to group goods into into so-called baskets of goods, and issue aggregate plan targets.
This is frankly a very shitty way of planning things, and it should not be construed that I am in favor of the ad-hoc planning system used in the USSR.
I am merely borrowing the terminology.
There are more ways in which Gosplan failed to produce rational plans, but such criticism I leave for a potential future post.</p>
<p>The purpose of adding extra constraints like this is so that we can evaluate what happens if we decide to relax some set of demands (entries in <math>
<mi>d</mi>
</math>) to free up resources for other things.
The baskets then act as a set of "sanity checks" so that there is no catastrophic shortfall in essential goods.
In other words <math>
<mi>d</mi>
</math> can be viewed as a set of wants while <math>
<mi>f</mi>
</math> is a set of needs.
In liberal economics, wants and needs are considered demands of equal importance, but the scheme presented here gives us more "wiggle room".
Another use for these contraints is to be able to say "produce at least this many MWh of electricity", not caring particularly <em>how</em> that electricity is produced.
Then one can check what happens if coal fired power plants are successively shut down and replaced by nuclear and renewable power.</p>
<p>Finally there is a set of balance equations meant for the optimization to work on.
This can be things like labour time spent, CO2 released, capital stocks consumed and so on.
The balance equations can be sparse, but in these experiments I have chosen to make them dense.</p>
<p>For the balance equations the right-hand side is all zeroes.
Using non-zero values is possible, but they are easily subtracted away due to the presence of the identity matrix.
Using zeroes increases the sparsity of the system and hence makes a solution easier to compute.</p>
<p>Finally, all variables must be positive.</p>
<p>In summary the system looks like this:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>S</mi><mspace width="0"/><mi>x</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><mi>I</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mi>A</mi></mtd><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mi>B</mi></mtd><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mo lspace="0" rspace="0">-</mo><mi>O</mi></mtd><mtd><mi>I</mi></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow><mspace width="0.167em"/><mi>x</mi><mo lspace="0.278em" rspace="0.278em">≥</mo><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><mi>d</mi></mtd></mtr><mtr><mtd><mi>f</mi></mtd></mtr><mtr><mtd><mn>0</mn></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow><mo lspace="0.278em" rspace="0.278em">=</mo><mi>b</mi></mrow>
</math>
</span></p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>A</mi><mo lspace="0.278em" rspace="0.278em">∈</mo><msup><mi mathvariant="double-struck">R</mi><mrow><mi>v</mi><mo lspace="0" rspace="0">×</mo><mi>v</mi></mrow></msup><mo lspace="0" rspace="0.500em">,</mo><mi>B</mi><mo lspace="0.278em" rspace="0.278em">∈</mo><msup><mi mathvariant="double-struck">R</mi><mrow><mi>w</mi><mo lspace="0" rspace="0">×</mo><mi>v</mi></mrow></msup><mo lspace="0" rspace="0.500em">,</mo><mi>O</mi><mo lspace="0.278em" rspace="0.278em">∈</mo><msup><mi mathvariant="double-struck">R</mi><mrow><mi>o</mi><mo lspace="0" rspace="0">×</mo><mi>v</mi></mrow></msup></mrow>
</math>
</span></p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>S</mi><mo lspace="0.278em" rspace="0.278em">∈</mo><msup><mi mathvariant="double-struck">R</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>v</mi><mo lspace="0" rspace="0">+</mo><mi>w</mi><mo lspace="0" rspace="0">+</mo><mi>o</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0">×</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>v</mi><mo lspace="0" rspace="0">+</mo><mi>o</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msup></mrow>
</math>
</span></p>
<p>The goal of the solver is to find the optimal solution <math>
<msub><mi>x</mi><mo>*</mo></msub>
</math> defined as follows:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msub><mi>x</mi><mo>*</mo></msub><mo lspace="0.278em" rspace="0.278em">=</mo><munder><mrow><mi>arg</mi><mspace width="0.167em"/><mi>min</mi></mrow><mstyle scriptlevel="1"><mtable rowspacing="0.3ex"><mtr><mtd><mi>S</mi><mspace width="0"/><mi>x</mi><mo lspace="0" rspace="0">≥</mo><mi>b</mi></mtd></mtr><mtr><mtd><mi>x</mi><mo lspace="0" rspace="0">≥</mo><mn>0</mn></mtd></mtr></mtable></mstyle></munder><munderover><mo lspace="0.167em" rspace="0.167em" stretchy="false" movablelimits="false">∑</mo><mrow><mi>i</mi><mo lspace="0" rspace="0">=</mo><mi>v</mi><mo lspace="0" rspace="0">+</mo><mn>1</mn></mrow><mrow><mi>v</mi><mo lspace="0" rspace="0">+</mo><mi>o</mi></mrow></munderover><msub><mi>x</mi><mi>i</mi></msub><mo lspace="0.278em" rspace="0.278em">=</mo><munder><mrow><mi>arg</mi><mspace width="0.167em"/><mi>min</mi></mrow><mstyle scriptlevel="1"><mtable rowspacing="0.3ex"><mtr><mtd><mi>S</mi><mspace width="0"/><mi>x</mi><mo lspace="0" rspace="0">≥</mo><mi>b</mi></mtd></mtr><mtr><mtd><mi>x</mi><mo lspace="0" rspace="0">≥</mo><mn>0</mn></mtd></mtr></mtable></mstyle></munder><mspace width="0.167em"/><msup><mi>c</mi><mi>T</mi></msup><mspace width="0"/><mi>x</mi></mrow>
</math>
</span></p>
<p>­<math>
<mi>c</mi>
</math> is a vector of <math>
<mi>v</mi>
</math> zeroes followed by <math>
<mi>o</mi>
</math> ones.</p>
<p>The structure described above makes computing an initial strictly feasible solution straightforward:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msub><mi>x</mi><mi>v</mi></msub><mo lspace="0.278em" rspace="0.278em">=</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>I</mi><mo lspace="0.222em" rspace="0.222em">-</mo><mi>A</mi><msup><mo lspace="0" rspace="0" stretchy="false">)</mo><mrow><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow></msup><mi>d</mi></mrow>
</math>
</span></p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>u</mi><mo lspace="0.278em" rspace="0.278em">=</mo><munder><mi>max</mi><mi>i</mi></munder><mspace width="0.167em"/><mfrac><msub><mi>f</mi><mi>i</mi></msub><mrow><msub><mi>B</mi><mi>i</mi></msub><mspace width="0"/><msub><mi>x</mi><mi>v</mi></msub></mrow></mfrac></mrow>
</math>
</span></p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msub><mi>x</mi><mi>o</mi></msub><mo lspace="0.278em" rspace="0.278em">=</mo><mi>O</mi><mspace width="0"/><msub><mi>x</mi><mi>v</mi></msub></mrow>
</math>
</span></p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msub><mi>x</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>0</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1</mn><mo lspace="0" rspace="0">.</mo><mn>1</mn><mspace width="0.167em"/><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><mi>u</mi><mspace width="0"/><msub><mi>x</mi><mi>v</mi></msub></mtd></mtr><mtr><mtd><msub><mi>x</mi><mi>o</mi></msub></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow></mrow>
</math>
</span></p>
<p>In other words, first a Leontief solution <math>
<msub><mi>x</mi><mi>v</mi></msub>
</math> is computed for the coefficient matrix.
Then a value <math>
<mi>u</mi>
</math> is computed which makes <math>
<mrow><mi>u</mi><mspace width="0"/><msub><mi>x</mi><mi>v</mi></msub></mrow>
</math> satisfy the basket constraints.
Then <math>
<msub><mi>x</mi><mi>o</mi></msub>
</math> is computed so that the balance equations are satisfied.
The final <math>
<msub><mi>x</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>0</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math> is assembled from <math>
<msub><mi>x</mi><mi>v</mi></msub>
</math>, <math>
<msub><mi>x</mi><mi>o</mi></msub>
</math> and <math>
<mi>u</mi>
</math> and scaled up by 10% so that it forms a solution that is strictly inside the feasible set.</p>
<p>On to the technical coefficients:</p>
<h3>Price's model</h3>
<p>Since industries pop up over time it seems reasonable to pick a model that is designed to produce power-law distributed graphs.
One such model is <a href="https://en.wikipedia.org/wiki/Price's_model">Price's model</a>, named after Derek J. de Solla Price.
This model is intended to model citation networks, which grow over time. More famous papers tend to be cited more often, and the citations form a directed acyclic graph (DAG).
Price's model results in that the distributions of citations follows a power law.</p>
<p>One drawback of Price's model as applied to economics is that real world economies do not look like a DAG.
Recycling especially breaks Price's model.
Nevertheless this model is useful because the distribution of row and column ranks is known.
Since the resulting incidence matrix is triangular, computing <math>
<msub><mi>x</mi><mi>v</mi></msub>
</math> is especially easy for this model, requiring only <math>
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>nnz</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>A</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> operations.</p>
<p>The sparsity pattern of the Price model looks like this:</p>
<p><img style="display:block;width:75%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/model_economy_solver/price/spy.png" alt="Price sparsity pattern"/></p>
<p>The triangular structure is apparent, as are the coefficients for the baskets and balance equations.
To me this model seems to result in an overemphasis of very few core industries.
It is also naïve in that it assumes old established industries do not make use of new technology.
This is also not the model I started my experiments with.</p>
<h3>Interdependent model</h3>
<p>The initial model used in my experiments is one where industries grow interdependent over time.
It differs from Price's model in that after each new node added, <math>
<mi>q</mi>
</math> new links are made equiprobably between any pair of nodes added so far.
This produces a matrix where non-zeroes are clustered in the upper left corner, growing more sparse toward the right and the bottom:</p>
<p><img style="display:block;width:75%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/model_economy_solver/spy.png" alt="Interdependent sparsity pattern"/></p>
<p>Here the economy is quite explicitly <em>not</em> a DAG.
Computing <math>
<msub><mi>x</mi><mi>v</mi></msub>
</math> is also more expensive, but still quite cheap using iterative methods.
We could also choose to compute the inverse of the upper left block of core industries explicitly, which would be useful as a preconditioner.</p>
<h2>Optimality and the duality gap</h2>
<p>When we're optimizing it is useful to know whether we are close enough to the optimal solution.
We'd like some sense of how much "room" there is for further optimization, preferably some lower bound.
If we know that we are within say 1% of this lower bound then we can stop.
Such lower bounds are given by feasible solutions to the <a href="https://en.wikipedia.org/wiki/Dual_linear_program">dual</a> of our starting program.</p>
<p>Instead of seeking the minimal solution to the primal:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msub><mi>x</mi><mo>*</mo></msub><mo lspace="0.278em" rspace="0.278em">=</mo><munder><mrow><mi>arg</mi><mspace width="0.167em"/><mi>min</mi></mrow><mstyle scriptlevel="1"><mtable rowspacing="0.3ex"><mtr><mtd><mi>S</mi><mspace width="0"/><mi>x</mi><mo lspace="0" rspace="0">≥</mo><mi>b</mi></mtd></mtr><mtr><mtd><mi>x</mi><mo lspace="0" rspace="0">≥</mo><mn>0</mn></mtd></mtr></mtable></mstyle></munder><mspace width="0.167em"/><msup><mi>c</mi><mi>T</mi></msup><mspace width="0"/><mi>x</mi></mrow>
</math>
</span></p>
<p>we instead seek to maximize its dual:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msub><mi>λ</mi><mo>*</mo></msub><mo lspace="0.278em" rspace="0.278em">=</mo><munder><mrow><mi>arg</mi><mspace width="0.167em"/><mi>max</mi></mrow><mstyle scriptlevel="1"><mtable rowspacing="0.3ex"><mtr><mtd><msup><mi>λ</mi><mi>T</mi></msup><mspace width="0"/><mi>S</mi><mo lspace="0" rspace="0">≤</mo><msup><mi>c</mi><mi>T</mi></msup></mtd></mtr><mtr><mtd><mi>λ</mi><mo lspace="0" rspace="0">≥</mo><mn>0</mn></mtd></mtr></mtable></mstyle></munder><mspace width="0.167em"/><msup><mi>b</mi><mi>T</mi></msup><mspace width="0"/><mi>λ</mi></mrow>
</math>
</span></p>
<p>By the <a href="https://en.wikipedia.org/wiki/Dual_linear_program#Strong_duality">strong duality theorem</a> we know that if we have <math>
<msub><mi>λ</mi><mo>*</mo></msub>
</math> then we also have <math>
<msub><mi>x</mi><mo>*</mo></msub>
</math> and <math>
<mrow><msup><mi>b</mi><mi>T</mi></msup><mspace width="0"/><msub><mi>λ</mi><mo>*</mo></msub><mo lspace="0.278em" rspace="0.278em">=</mo><msup><mi>c</mi><mi>T</mi></msup><mspace width="0"/><msub><mi>x</mi><mo>*</mo></msub></mrow>
</math>.</p>
<p>All that remains is to compute an initial feasible <math>
<msub><mi>λ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>0</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math>. I will leave this out for now because my current solution is honestly too much of a hack.</p>
<h2>Central path methods</h2>
<p>The solver used here is in the class of central path methods.
Such solvers date back to James Renegar's 1988 paper <a href="doi:10.1007/BF01580724">A polynomial-time algorithm, based on Newton's method, for linear programming</a>.
The idea is to define a measure of "centrality" such that there is a single point that is "equidistant" from all constraints plus the constraint <math>
<mrow><msup><mi>c</mi><mi>T</mi></msup><mspace width="0"/><mi>x</mi><mo lspace="0.278em" rspace="0.278em">≥</mo><msub><mi>k</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub></mrow>
</math> defined by the objective function.
­<math>
<msub><mi>x</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math> is near this central point at the start of every iteration in the algorithm.
­<math>
<msub><mi>k</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math> is then updated to <math>
<mrow><msub><mi>k</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0">+</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0.278em" rspace="0.278em">=</mo><mi>δ</mi><mspace width="0"/><msup><mi>c</mi><mi>T</mi></msup><mspace width="0"/><msub><mi>x</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0.222em" rspace="0.222em">+</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>1</mn><mo lspace="0.222em" rspace="0.222em">-</mo><mi>δ</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><msub><mi>k</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub></mrow>
</math>, and then a re-centering step is taken to produce <math>
<msub><mi>x</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0">+</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math>.</p>
<p>Renegar shows that if <math>
<mrow><mi>δ</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><mo lspace="0" rspace="0" stretchy="false">(</mo><mn>13</mn><msqrt><mi>m</mi></msqrt><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> where <math>
<mi>m</mi>
</math> is the number of rows in the system matrix (<math>
<mrow><mi>m</mi><mo lspace="0.278em" rspace="0.278em">></mo><mi>n</mi></mrow>
</math>), then the distance to <math>
<msub><mi>x</mi><mo>*</mo></msub>
</math> is halved every <math>
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msqrt><mi>m</mi></msqrt><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> step.
Each step amounts to a single Newton step, which takes <math>
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>m</mi><mspace width="0"/><msup><mi>n</mi><mrow><mi>ω</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow></msup><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> operations where <math>
<mi>ω</mi>
</math> is the matrix multiplication constant.
Achieving <math>
<mi>L</mi>
</math> bits of accuracy therefore takes <math>
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msup><mi>m</mi><mrow><mn>1</mn><mo lspace="0" rspace="0">.</mo><mn>5</mn></mrow></msup><mspace width="0"/><msup><mi>n</mi><mrow><mi>ω</mi><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow></msup><mspace width="0"/><mi>L</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> operations.</p>
<p>For the kind of linear programs we're talking about here, we can do quite a bit better than this.
Renegar's result merely says how much time it takes <em>at most</em>.</p>
<h3>Predictor-corrector methods</h3>
<p>It turns out that there is a limit to how much the central path bends.
This suggest an optimization: compute the tangent of the central path and use that as a predictor.
Move <math>
<msub><mi>x</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math> some distance along the tangent, then perform a correction step to get back near the central path.
At the same time update <math>
<msub><mi>k</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math>.</p>
<p>Assuming the central path doesn't bend too much, this allows us to take steps much larger than <math>
<mi>δ</mi>
</math>.
In my experiments, if steps 75% of the way to the nearest constraint are taken, in the direction of the tangent, then I typically get 1-2 bits of accuracy rather than the <math>
<mrow><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">/</mo><msqrt><mi>m</mi></msqrt></mrow>
</math> bits with Renegar.
The following two pictures hopefully explain the idea:</p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/model_economy_solver/central-path-1.svg" alt="First step in algorithm"/></p>
<p>The dashed line is the tangent of the central path at <math>
<msub><mi>x</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math>.
This can be computed either numerically or analytically.
The current algorithm does it numerically.</p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/model_economy_solver/central-path-2.svg" alt="Second step in algorithm"/></p>
<p>An intermediate step is taken along the tangent, then <math>
<msub><mi>k</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0">+</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math> is computed.
Currently I update <math>
<mi>k</mi>
</math> so that the distance is half the distance of the next closest constraint in the system.
Finally the intermediate point is re-centered, producing <math>
<msub><mi>x</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0">+</mo><mn>1</mn><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub>
</math>.</p>
<p>The downside of this method is that re-centering requires more work.
Interestingly it never takes more than a few Newton steps, certainly much fewer than <math>
<msqrt><mi>m</mi></msqrt>
</math>.
The work required for centering is also very parallelizable.
It amounts to solving for <math>
<mi>h</mi>
</math> in the following system:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msub><mi mathvariant="normal">Λ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0.278em" rspace="0.278em">=</mo><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><mi>diag</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>S</mi><mspace width="0"/><msub><mi>x</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0.222em" rspace="0.222em">-</mo><mi>b</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mtd><mtd/><mtd/></mtr><mtr><mtd/><mtd><mi>diag</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msub><mi>x</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0" rspace="0" stretchy="false">)</mo></mtd><mtd/></mtr><mtr><mtd/><mtd/><mtd><msub><mi>k</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub><mo lspace="0.222em" rspace="0.222em">-</mo><msup><mi>c</mi><mi>T</mi></msup><mspace width="0"/><msub><mi>x</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow></msub></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow></mrow>
</math>
</span></p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><msup><mi>S</mi><mi>T</mi></msup></mtd><mtd><mi>I</mi></mtd><mtd><mo lspace="0" rspace="0">-</mo><mi>c</mi></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow><mspace width="0.167em"/><msubsup><mi mathvariant="normal">Λ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow><mrow><mo lspace="0" rspace="0">-</mo><mn>2</mn></mrow></msubsup><mspace width="0.167em"/><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><mi>S</mi></mtd></mtr><mtr><mtd><mi>I</mi></mtd></mtr><mtr><mtd><mo lspace="0" rspace="0">-</mo><msup><mi>c</mi><mi>T</mi></msup></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow><mspace width="0.167em"/><mi>h</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mo lspace="0" rspace="0.167em">-</mo><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><msup><mi>S</mi><mi>T</mi></msup></mtd><mtd><mi>I</mi></mtd><mtd><mo lspace="0" rspace="0">-</mo><mi>c</mi></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow><mspace width="0.167em"/><msubsup><mi mathvariant="normal">Λ</mi><mrow><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>i</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow><mrow><mo lspace="0" rspace="0">-</mo><mn>1</mn></mrow></msubsup><mn mathvariant="bold">1</mn></mrow>
</math>
</span></p>
<p>­<math>
<mn mathvariant="bold">1</mn>
</math> is a vector of all ones.
The left-hand matrix in the second equation is symmetric and positive definite (SPD).
This means that the <a href="https://en.wikipedia.org/wiki/Conjugate_gradient_method">conjugate gradient method (CG)</a> can be used.
For CG the left-hand matrix does not need to be formed explicitly.
Therefore each CG iteration only needs to perform <math>
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>nnz</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>S</mi><mo lspace="0" rspace="0" stretchy="false">)</mo><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> work.</p>
<p>A similar process is done for the dual problem, except all matrices are transposed, some signs change and <math>
<mi>c</mi>
</math> and <math>
<mi>b</mi>
</math> swap roles.</p>
<h2>Results</h2>
<p>Tests were run on an <a href="https://support.hp.com/us-en/document/c02781693">HP Compaq 8200 Elite SFF PC (XL510AV)</a> with an i7-2600 @ 3.40GHz and 8 GiB 1333 MHz DDR3 running <a href="https://www.debian.org/">Debian GNU/Linux 10 (buster)</a>.
The implementation is written in <a href="https://www.gnu.org/software/octave/index">GNU Octave</a>, which parallelizes some of the computations but far from all of them.</p>
<p>­<math>
<mi>v</mi>
</math> is swept over the numbers 300, 1000, 3000, 10000, 30000, 100000, 300000.
The other parameters are <math>
<mi>q</mi>
</math> = 160, <math>
<mi>w</mi>
</math> = 10, <math>
<mi>r</mi>
</math> = 160 and <math>
<mi>o</mi>
</math> = 10.
Wall time, the number of CG iterations and the final duality gap are measured for each run.
Runs are made for both models.
Stopping conditions are either of:</p>
<ul>
<li>the duality gap is less than 1%</li>
<li>less than 1 ppm improvement was made to the gap in the last iteration</li>
</ul>
<p>The latter condition is necessary because of a bug in the code that I have not yet tracked down.
One run failed to find even a decent solution, <math>
<mi>v</mi>
</math> = 100000 for the Price model.
I have omitted that run from the results.
Similarly <math>
<mi>v</mi>
</math> = 1000000 fails to find a reasonable solution for both models, which is the reason for the 300000 stopping point.</p>
<p>The following graph plots the wall times of each run against <math>
<mrow><mi>nnz</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><mi>S</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math> and shows power laws fitted to the results:</p>
<p><img style="display:block;width:75%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/model_economy_solver/results-fit.png" alt="Price sparsity pattern"/></p>
<p>The nearly linear fit is very promising.
Keep in mind that this is for this specific class of problems, and almost surely does not apply to solving LPs in general.</p>
<p>Some of the runs don't quite make it below the 1% mark:</p>
<p><img style="display:block;width:75%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/model_economy_solver/results-gap.png" alt="Price sparsity pattern"/></p>
<p>This suggests that there is more work to be done.
A similarly shaped graph comes out when plotting the total number of conjugate gradient steps vs the number of industries:</p>
<p><img style="display:block;width:75%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/model_economy_solver/results-steps.png" alt="Price sparsity pattern"/></p>
<p>Interestingly the number of steps is between 1000 and 2000 for the runs that do find a 1% solution.</p>
<h2>Parallelism</h2>
<p>The central operation in Renegar's algorithm and its descendants is the centering Newton step.
Recent work in the field has focused on speeding this up by maintaining an approximate inverse of the left-hand matrix.
See for example the work of Lee and Sidford.
These efforts are serial, and not as useful for dealing with sufficiently large systems.</p>
<p>Another way to deal with this is to parallelize the Newton solver.
If we let the number of nodes scale with the number of non-zeroes in <math>
<mi>S</mi>
</math> then the time for each step becomes constant, plus some communication overhead.
If we use Renegar's more conservative result for the number of steps, then the total time to solve the LP is <math>
<mrow><mi>O</mi><mo lspace="0" rspace="0" stretchy="false">(</mo><msqrt><mi>m</mi></msqrt><mi>L</mi><mo lspace="0" rspace="0" stretchy="false">)</mo></mrow>
</math>.
From the experiment presented here we know that a single computer with 8 GiB of RAM can deal with a linear program corresponding to an economy with one million industries.
It therefore does not seem unreasonable that the entirety of the world economy, a system with billions of industries, could be planned using a relatively modest computer cluster.</p>Some example economic linear programs2021-02-08T23:30:25+01:002021-02-08T23:30:25+01:00tomastag:www.härdin.se,2021-02-08:/blog/2021/02/08/some-example-economic-linear-programs/<p>In <a href="http://www.härdin.se/blog/2021/02/04/cybernetics-politics-and-sparse-linear-algebra/">the previous post</a> I laid out an outline for the case for computerized planning.
In this post I will present some simple examples that should help get the point across.</p>
<h2>A tiny example economy</h2>
<p>In these examples I will use an economy which produces only one good.
That good …</p><p>In <a href="http://www.härdin.se/blog/2021/02/04/cybernetics-politics-and-sparse-linear-algebra/">the previous post</a> I laid out an outline for the case for computerized planning.
In this post I will present some simple examples that should help get the point across.</p>
<h2>A tiny example economy</h2>
<p>In these examples I will use an economy which produces only one good.
That good could be anything, for example food.
There are two technologies available to produce this good: techA and techB.
The difference between the two technologies is that techA uses 2 units of labour and 3 units of CO2 emissions per unit of output while techB is the opposite: 3 units of labour and 2 units of CO2.
They complement each other, and the choice between them depends on whether we're minimizing labour input, CO2 emissions or some combination of the two.
Given demand <math>
<mi>d</mi>
</math>, maximum labour <math>
<msub><mi>L</mi><mrow><mi>m</mi><mspace width="0"/><mi>a</mi><mspace width="0"/><mi>x</mi></mrow></msub>
</math> and maximum CO2 emission <math>
<msub><mi>C</mi><mrow><mi>m</mi><mspace width="0"/><mi>a</mi><mspace width="0"/><mi>x</mi></mrow></msub>
</math>, we have the following matrix equation:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><mn>1</mn></mtd><mtd><mn>1</mn></mtd></mtr><mtr><mtd><mo lspace="0" rspace="0">-</mo><mn>2</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>3</mn></mtd></mtr><mtr><mtd><mo lspace="0" rspace="0">-</mo><mn>3</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>2</mn></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow><mspace width="0.167em"/><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><msub><mi>x</mi><mi>A</mi></msub></mtd></mtr><mtr><mtd><msub><mi>x</mi><mi>B</mi></msub></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow><mo lspace="0.278em" rspace="0.278em">≥</mo><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><mi>d</mi></mtd></mtr><mtr><mtd><mo lspace="0" rspace="0">-</mo><msub><mi>L</mi><mrow><mi>m</mi><mspace width="0"/><mi>a</mi><mspace width="0"/><mi>x</mi></mrow></msub></mtd></mtr><mtr><mtd><mo lspace="0" rspace="0">-</mo><msub><mi>C</mi><mrow><mi>m</mi><mspace width="0"/><mi>a</mi><mspace width="0"/><mi>x</mi></mrow></msub></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow></mrow>
</math>
</span></p>
<p>Both <math>
<msub><mi>x</mi><mi>A</mi></msub>
</math> and <math>
<msub><mi>x</mi><mi>B</mi></msub>
</math> are non-negative, meaning <math>
<mrow><mi>x</mi><mo lspace="0.278em" rspace="0.278em">≥</mo><mn>0</mn></mrow>
</math>.
All <math>
<mi>x</mi>
</math> are implied to be non-negative for the rest of this article.</p>
<p>On its own the preceeding equation is not very useful since neither labour nor CO2 are variables.
To be able to optimize on either, the system needs to be extended.
Let's start with minimizing labour, which requires adding a third variable <math>
<msub><mi>x</mi><mi>L</mi></msub>
</math>:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><mn>1</mn></mtd><mtd><mn>1</mn></mtd><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mo lspace="0" rspace="0">-</mo><mn>2</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>3</mn></mtd><mtd><mn>1</mn></mtd></mtr><mtr><mtd><mo lspace="0" rspace="0">-</mo><mn>3</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>2</mn></mtd><mtd><mn>0</mn></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow><mspace width="0.167em"/><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><msub><mi>x</mi><mi>A</mi></msub></mtd></mtr><mtr><mtd><msub><mi>x</mi><mi>B</mi></msub></mtd></mtr><mtr><mtd><msub><mi>x</mi><mi>L</mi></msub></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow><mo lspace="0.278em" rspace="0.278em">≥</mo><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><mi>d</mi></mtd></mtr><mtr><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mo lspace="0" rspace="0">-</mo><msub><mi>C</mi><mrow><mi>m</mi><mspace width="0"/><mi>a</mi><mspace width="0"/><mi>x</mi></mrow></msub></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow></mrow>
</math>
</span></p>
<p>The new column in the matrix turns the second row into a "balance equation".
Since we are minimizing <math>
<msub><mi>x</mi><mi>L</mi></msub>
</math> the goal is to add as little of it as possible while still keeping the sum of the labour added and the labour consumed non-negative.</p>
<p>The optimal solution <math>
<msub><mi>x</mi><mo>*</mo></msub>
</math> that we seek is given by:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msub><mi>x</mi><mo>*</mo></msub><mo lspace="0.278em" rspace="0.278em">=</mo><munder><mrow><mi>arg</mi><mspace width="0.167em"/><mi>min</mi></mrow><mi>x</mi></munder><mspace width="0.167em"/><msup><mi>c</mi><mi>T</mi></msup><mspace width="0"/><mi>x</mi></mrow>
</math>
</span></p>
<p>where</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mi>c</mi><mo lspace="0.278em" rspace="0.278em">=</mo><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mn>1</mn></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow></mrow>
</math>
</span></p>
<p>The solution depends only on <math>
<mi>d</mi>
</math> and <math>
<msub><mi>C</mi><mrow><mi>m</mi><mspace width="0"/><mi>a</mi><mspace width="0"/><mi>x</mi></mrow></msub>
</math>.
If we let <math>
<mrow><msub><mi>C</mi><mrow><mi>m</mi><mspace width="0"/><mi>a</mi><mspace width="0"/><mi>x</mi></mrow></msub><mo lspace="0.278em" rspace="0.278em">=</mo><mn>5</mn></mrow>
</math> then we can sweep <math>
<mi>d</mi>
</math> from 0 to 2.5.
The following <a href="https://www.gnu.org/software/bash/">bash</a> script does this, has <a href="http://lpsolve.sourceforge.net/5.5/">lp_solve</a> solve the resulting linear program, parses the result and spits out <a href="https://www.gnu.org/software/octave/index">Octave</a> code the renders the plot below:</p>
<div class="highlight"><pre><span></span><code><span class="ch">#!/bin/bash</span>
<span class="c1"># makes seq use decimal dots in Swedish locale, not commas</span>
<span class="nb">export</span><span class="w"> </span><span class="nv">LANG</span><span class="o">=</span>C
<span class="nb">echo</span><span class="w"> </span><span class="s2">"x=["</span>
<span class="k">for</span><span class="w"> </span>d<span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="k">$(</span>seq<span class="w"> </span><span class="m">0</span><span class="w"> </span><span class="m">0</span>.05<span class="w"> </span><span class="m">2</span>.5<span class="k">)</span>
<span class="k">do</span>
<span class="w"> </span>lp_solve<span class="w"> </span><span class="s"><<EOF > /tmp/lp_result</span>
<span class="s">min: xl;</span>
<span class="s">xa + xb >= $d;</span>
<span class="s">-2 xa - 3 xb + xl >= 0;</span>
<span class="s">-3 xa - 2 xb >= -5;</span>
<span class="s">EOF</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span>var<span class="w"> </span><span class="k">in</span><span class="w"> </span>xa<span class="w"> </span>xb<span class="w"> </span>xl
<span class="w"> </span><span class="k">do</span>
<span class="w"> </span><span class="nv">V</span><span class="o">=</span><span class="k">$(</span>grep<span class="w"> </span><span class="nv">$var</span><span class="w"> </span>/tmp/lp_result<span class="w"> </span><span class="p">|</span><span class="w"> </span>sed<span class="w"> </span>-e<span class="w"> </span><span class="s1">'s/^[^0-9]*//'</span><span class="k">)</span>
<span class="w"> </span><span class="nb">export</span><span class="w"> </span><span class="nv">$var</span><span class="o">=</span><span class="nv">$V</span>
<span class="w"> </span><span class="k">done</span>
<span class="w"> </span><span class="nb">echo</span><span class="w"> </span><span class="s2">"</span><span class="nv">$d</span><span class="s2">,</span><span class="nv">$xa</span><span class="s2">,</span><span class="nv">$xb</span><span class="s2">,</span><span class="nv">$xl</span><span class="s2">;"</span>
<span class="k">done</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"];"</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"plot(x(:,1),x(:,2),x(:,1),x(:,3),x(:,1),x(:,4));"</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"legend('techA','techB','labour','location','northeastoutside');"</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"xlabel('Demand');"</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"ylabel('Intensity');"</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"title('CO_2 constrained labour-minimizing economy');"</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"axis([0,2.5,0,8]);"</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"print('tiny_economy.png');"</span>
</code></pre></div>
<p><img style="display:block;width:75%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/files/tiny_economy/tiny_economy.png" alt="The plot generated by the above bash+Octave code"/></p>
<p>We can see that techA is preferred as long as CO2 emissions stay below the limit.
Once demand goes past 1.66, techB starts getting used and the marginal demand for labour increases.</p>
<p>If we instead minimize CO2 emissions then the result looks much the same, except techA and techB swap roles:</p>
<div class="highlight"><pre><span></span><code><span class="ch">#!/bin/bash</span>
<span class="c1"># makes seq use decimal dots in Swedish locale, not commas</span>
<span class="nb">export</span><span class="w"> </span><span class="nv">LANG</span><span class="o">=</span>C
<span class="nb">echo</span><span class="w"> </span><span class="s2">"x=["</span>
<span class="k">for</span><span class="w"> </span>d<span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="k">$(</span>seq<span class="w"> </span><span class="m">0</span><span class="w"> </span><span class="m">0</span>.05<span class="w"> </span><span class="m">2</span>.5<span class="k">)</span>
<span class="k">do</span>
<span class="w"> </span>lp_solve<span class="w"> </span><span class="s"><<EOF > /tmp/lp_result</span>
<span class="s">min: xc;</span>
<span class="s">xa + xb >= $d;</span>
<span class="s">-2 xa - 3 xb >= -5;</span>
<span class="s">-3 xa - 2 xb + xc >= 0;</span>
<span class="s">EOF</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span>var<span class="w"> </span><span class="k">in</span><span class="w"> </span>xa<span class="w"> </span>xb<span class="w"> </span>xc
<span class="w"> </span><span class="k">do</span>
<span class="w"> </span><span class="nv">V</span><span class="o">=</span><span class="k">$(</span>grep<span class="w"> </span><span class="nv">$var</span><span class="w"> </span>/tmp/lp_result<span class="w"> </span><span class="p">|</span><span class="w"> </span>sed<span class="w"> </span>-e<span class="w"> </span><span class="s1">'s/^[^0-9]*//'</span><span class="k">)</span>
<span class="w"> </span><span class="nb">export</span><span class="w"> </span><span class="nv">$var</span><span class="o">=</span><span class="nv">$V</span>
<span class="w"> </span><span class="k">done</span>
<span class="w"> </span><span class="nb">echo</span><span class="w"> </span><span class="s2">"</span><span class="nv">$d</span><span class="s2">,</span><span class="nv">$xa</span><span class="s2">,</span><span class="nv">$xb</span><span class="s2">,</span><span class="nv">$xc</span><span class="s2">;"</span>
<span class="k">done</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"];"</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"plot(x(:,1),x(:,2),x(:,1),x(:,3),x(:,1),x(:,4));"</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"legend('techA','techB','CO_2','location','northeastoutside');"</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"xlabel('Demand');"</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"ylabel('Intensity');"</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"title('CO_2-minimizing labour constrained economy');"</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"axis([0,2.5,0,8]);"</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"print('tiny_economy2.png');"</span>
</code></pre></div>
<p><img style="display:block;width:75%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/files/tiny_economy/tiny_economy2.png" alt="The plot generated by the above bash+Octave code. techA and techB are switched compared to the previous plot"/></p>
<p>In reality we may want to minimize some combination of labour and CO2. The following is an interesting example:</p>
<div class="highlight"><pre><span></span><code><span class="ch">#!/bin/bash</span>
<span class="c1"># makes seq use decimal dots in Swedish locale, not commas</span>
<span class="nb">export</span><span class="w"> </span><span class="nv">LANG</span><span class="o">=</span>C
<span class="nb">echo</span><span class="w"> </span><span class="s2">"x=["</span>
<span class="k">for</span><span class="w"> </span>d<span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="k">$(</span>seq<span class="w"> </span><span class="m">0</span><span class="w"> </span><span class="m">0</span>.05<span class="w"> </span><span class="m">2</span>.5<span class="k">)</span>
<span class="k">do</span>
<span class="w"> </span>lp_solve<span class="w"> </span><span class="s"><<EOF > /tmp/lp_result</span>
<span class="s">min: xl + 0.5 xc;</span>
<span class="s">xa + xb >= $d;</span>
<span class="s">-2 xa - 3 xb + xl >= 0;</span>
<span class="s">-3 xa - 2 xb + xc >= 0;</span>
<span class="s">xa <= 1.5;</span>
<span class="s">xb <= 1.5;</span>
<span class="s">xc <= 6;</span>
<span class="s">EOF</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span>var<span class="w"> </span><span class="k">in</span><span class="w"> </span>xa<span class="w"> </span>xb<span class="w"> </span>xl<span class="w"> </span>xc
<span class="w"> </span><span class="k">do</span>
<span class="w"> </span><span class="nv">V</span><span class="o">=</span><span class="k">$(</span>grep<span class="w"> </span><span class="nv">$var</span><span class="w"> </span>/tmp/lp_result<span class="w"> </span><span class="p">|</span><span class="w"> </span>sed<span class="w"> </span>-e<span class="w"> </span><span class="s1">'s/^[^0-9]*//'</span><span class="k">)</span>
<span class="w"> </span><span class="nb">export</span><span class="w"> </span><span class="nv">$var</span><span class="o">=</span><span class="nv">$V</span>
<span class="w"> </span><span class="k">done</span>
<span class="w"> </span><span class="nb">echo</span><span class="w"> </span><span class="s2">"</span><span class="nv">$d</span><span class="s2">,</span><span class="nv">$xa</span><span class="s2">,</span><span class="nv">$xb</span><span class="s2">,</span><span class="nv">$xl</span><span class="s2">,</span><span class="nv">$xc</span><span class="s2">;"</span>
<span class="k">done</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"];"</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"plot(x(:,1),x(:,2),x(:,1),x(:,3),x(:,1),x(:,4),x(:,1),x(:,5));"</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"legend('techA','techB','labour','CO_2','location','northeastoutside');"</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"xlabel('Demand');"</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"ylabel('Intensity');"</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"title('Combination economy');"</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"axis([0,2.5,0,8]);"</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"print('tiny_economy3.png');"</span>
</code></pre></div>
<p><img style="display:block;width:75%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/files/tiny_economy/tiny_economy3.png" alt="The plot generated by the above bash+Octave code. Behavious is much more interesting"/></p>
<p>In this example the capabilities of techA and techB are limited. Each can only produce 1.5 units of goods. Additionally, CO2 emissions are limited to 6 and we're trying to optimize for a mix that favours labour.
Three different regions are clearly visible. The first region is unconstrained, the second region is constrained by the capabilities of techA and the third region is constrained by CO2. As the marginal CO2 "demand"/budget decreases, the marginal demand for labour increases.</p>
<p>Incidentally, the equations for this system look like this:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msub><mi>x</mi><mo>*</mo></msub><mo lspace="0.278em" rspace="0.278em">=</mo><munder><mrow><mi>arg</mi><mspace width="0.167em"/><mi>min</mi></mrow><mi>x</mi></munder><mspace width="0.167em"/><msup><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mn>1</mn></mtd></mtr><mtr><mtd><mn>0</mn><mo lspace="0" rspace="0">.</mo><mn>5</mn></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow><mi>T</mi></msup><mspace width="0.167em"/><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><msub><mi>x</mi><mi>A</mi></msub></mtd></mtr><mtr><mtd><msub><mi>x</mi><mi>B</mi></msub></mtd></mtr><mtr><mtd><msub><mi>x</mi><mi>L</mi></msub></mtd></mtr><mtr><mtd><msub><mi>x</mi><mi>C</mi></msub></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow></mrow>
</math>
</span></p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><mn>1</mn></mtd><mtd><mn>1</mn></mtd><mtd><mn>0</mn></mtd><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mo lspace="0" rspace="0">-</mo><mn>2</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>3</mn></mtd><mtd><mn>1</mn></mtd><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mo lspace="0" rspace="0">-</mo><mn>3</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>2</mn></mtd><mtd><mn>0</mn></mtd><mtd><mn>1</mn></mtd></mtr><mtr><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd><mn>0</mn></mtd><mtd><mn>0</mn></mtd><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd><mn>0</mn></mtd><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd><mtd><mn>0</mn></mtd><mtd><mn>0</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd></mtr><mtr><mtd><mn>1</mn></mtd><mtd><mn>0</mn></mtd><mtd><mn>0</mn></mtd><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd><mtd><mn>1</mn></mtd><mtd><mn>0</mn></mtd><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd><mtd><mn>0</mn></mtd><mtd><mn>1</mn></mtd><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd><mtd><mn>0</mn></mtd><mtd><mn>0</mn></mtd><mtd><mn>1</mn></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow><mspace width="0.167em"/><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><msub><mi>x</mi><mi>A</mi></msub></mtd></mtr><mtr><mtd><msub><mi>x</mi><mi>B</mi></msub></mtd></mtr><mtr><mtd><msub><mi>x</mi><mi>L</mi></msub></mtd></mtr><mtr><mtd><msub><mi>x</mi><mi>C</mi></msub></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow><mo lspace="0.278em" rspace="0.278em">≥</mo><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><mi>d</mi></mtd></mtr><mtr><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0">.</mo><mn>5</mn></mtd></mtr><mtr><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0">.</mo><mn>5</mn></mtd></mtr><mtr><mtd><mo lspace="0" rspace="0">-</mo><mn>6</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow></mrow>
</math>
</span></p>
<p>Here I have chosen to make the non-negativity constraints on <math>
<mi>x</mi>
</math> explicit, to highlight that the full matrix is tall.
We can also see that the system is quite sparse and that it can be slightly simplified:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><msub><mi>x</mi><mo>*</mo></msub><mo lspace="0.278em" rspace="0.278em">=</mo><munder><mrow><mi>arg</mi><mspace width="0.167em"/><mi>min</mi></mrow><mi>x</mi></munder><mspace width="0.167em"/><msup><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><mn>1</mn></mtd></mtr><mtr><mtd><mn>0</mn><mo lspace="0" rspace="0">.</mo><mn>5</mn></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow><mi>T</mi></msup><mspace width="0.167em"/><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><msub><mi>x</mi><mi>L</mi></msub></mtd></mtr><mtr><mtd><msub><mi>x</mi><mi>C</mi></msub></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow></mrow>
</math>
</span></p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><mn>1</mn></mtd><mtd><mn>1</mn></mtd><mtd/><mtd/></mtr><mtr><mtd><mo lspace="0" rspace="0">-</mo><mn>2</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>3</mn></mtd><mtd><mn>1</mn></mtd><mtd/></mtr><mtr><mtd><mo lspace="0" rspace="0">-</mo><mn>3</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>2</mn></mtd><mtd/><mtd><mn>1</mn></mtd></mtr><mtr><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd/><mtd/><mtd/></mtr><mtr><mtd/><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd/><mtd/></mtr><mtr><mtd/><mtd/><mtd/><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd></mtr><mtr><mtd><mn>1</mn></mtd><mtd/><mtd/><mtd/></mtr><mtr><mtd/><mtd><mn>1</mn></mtd><mtd/><mtd/></mtr><mtr><mtd/><mtd/><mtd><mn>1</mn></mtd><mtd/></mtr><mtr><mtd/><mtd/><mtd/><mtd><mn>1</mn></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow><mspace width="0.167em"/><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><msub><mi>x</mi><mi>A</mi></msub></mtd></mtr><mtr><mtd><msub><mi>x</mi><mi>B</mi></msub></mtd></mtr><mtr><mtd><msub><mi>x</mi><mi>L</mi></msub></mtd></mtr><mtr><mtd><msub><mi>x</mi><mi>C</mi></msub></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow><mo lspace="0.278em" rspace="0.278em">≥</mo><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><mi>d</mi></mtd></mtr><mtr><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0">.</mo><mn>5</mn></mtd></mtr><mtr><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn><mo lspace="0" rspace="0">.</mo><mn>5</mn></mtd></mtr><mtr><mtd><mo lspace="0" rspace="0">-</mo><mn>6</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow></mrow>
</math>
</span></p>
<h2>Other examples</h2>
<h3>Chain economy</h3>
<p>A chain economy like A -> B -> C -> ... Z where each industry needs two units of the industry before it, one unit of labour and one unit of CO2, looks like this:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>2</mn></mtd><mtd/><mtd/><mtd/><mtd/><mtd/></mtr><mtr><mtd/><mtd><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>2</mn></mtd><mtd/><mtd/><mtd/><mtd/></mtr><mtr><mtd/><mtd/><mtd><mn>1</mn></mtd><mtd><mo>⋱</mo></mtd><mtd/><mtd/><mtd/></mtr><mtr><mtd/><mtd/><mtd/><mtd><mo>⋱</mo></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>2</mn></mtd><mtd/><mtd/></mtr><mtr><mtd/><mtd/><mtd/><mtd/><mtd><mn>1</mn></mtd><mtd/><mtd/></mtr><mtr><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mo lspace="0" rspace="0">.</mo><mo lspace="0" rspace="0">.</mo></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd><mn>1</mn></mtd><mtd/></mtr><mtr><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mo lspace="0" rspace="0">.</mo><mo lspace="0" rspace="0">.</mo></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd/><mtd><mn>1</mn></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow><mspace width="0.167em"/><mi>x</mi><mo lspace="0.278em" rspace="0.278em">≥</mo><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><msub><mi>d</mi><mi>A</mi></msub></mtd></mtr><mtr><mtd><msub><mi>d</mi><mi>B</mi></msub></mtd></mtr><mtr><mtd><msub><mi>d</mi><mi>C</mi></msub></mtd></mtr><mtr><mtd><mo>⋮</mo></mtd></mtr><mtr><mtd><msub><mi>d</mi><mi>Z</mi></msub></mtd></mtr><mtr><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow></mrow>
</math>
</span></p>
<h3>Service economy</h3>
<p>Services are industries which notionally require only labour.
In practice they require more than that, like office supplies.
Service workers also need to eat, but that is handled elsewhere in the equations.
Service industries do not emit CO2 on their own, but may do so indirectly, like all industries today.</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><mn>1</mn></mtd><mtd/><mtd/><mtd/><mtd/><mtd/></mtr><mtr><mtd/><mtd><mn>1</mn></mtd><mtd/><mtd/><mtd/><mtd/></mtr><mtr><mtd/><mtd/><mtd><mn>1</mn></mtd><mtd/><mtd/><mtd/></mtr><mtr><mtd/><mtd/><mtd/><mtd><mo>⋱</mo></mtd><mtd/><mtd/></mtr><mtr><mtd/><mtd/><mtd/><mtd/><mtd><mn>1</mn></mtd><mtd/></mtr><mtr><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mo lspace="0" rspace="0">.</mo><mo lspace="0" rspace="0">.</mo></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd><mn>1</mn></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow><mspace width="0.167em"/><mi>x</mi><mo lspace="0.278em" rspace="0.278em">≥</mo><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><msub><mi>d</mi><mi>A</mi></msub></mtd></mtr><mtr><mtd><msub><mi>d</mi><mi>B</mi></msub></mtd></mtr><mtr><mtd><msub><mi>d</mi><mi>C</mi></msub></mtd></mtr><mtr><mtd><mo>⋮</mo></mtd></mtr><mtr><mtd><msub><mi>d</mi><mi>Z</mi></msub></mtd></mtr><mtr><mtd><mn>0</mn></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow></mrow>
</math>
</span></p>
<h3>Food production</h3>
<p>To ensure everyone is fed and that there's a variety of foods available, one adds a number of constraints.
The most important of these are those for macronutrients like energy, carbohydrates, fat, protein and so on.
If we were to rely only on nutrients then the solution would likely end up picking a single crop like maize or sorghum.
While this keeps people fed, it would be a very depressing diet.</p>
<p>We can use statistics of what kinds of food people prefer and add a constraint for each one: produce at least <math>
<msub><mi>d</mi><mrow><mi>P</mi><mspace width="0"/><mi>o</mi></mrow></msub>
</math> potatoes, <math>
<msub><mi>d</mi><mrow><mi>C</mi><mspace width="0"/><mi>M</mi></mrow></msub>
</math> coconut milk, <math>
<msub><mi>d</mi><mrow><mi>H</mi><mspace width="0"/><mi>a</mi></mrow></msub>
</math> Habaneros and so on.
It is also the case that preferences vary with season and region.
We know with high certainty that demand for Julmust will be high for roughly two months around the winter solstice in Sweden,
but comparatively low the rest of the year.
A similar peak occurs around Easter for Påskmust.</p>
<p>Demand for some goods vary with a frequency different from that of the Gregorian year. For example goods associated with Ramadan and similar traditions that follow a lunar calendar.
For regional foods, sizeable diasporas must be accounted for.</p>
<p>For the <a href="https://en.wikipedia.org/wiki/Staple_food">ten staple foods listed on Wikipedia</a> the following LP for how much area to plant of each crop can be built:</p>
<p><span style="display:block;text-align:center"><math displaystyle="true">
<mrow><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><mo lspace="0" rspace="0">.</mo><mn>32</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>12</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>10</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>12</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>19</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>02</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>10</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>11</mn></mtd><mtd><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>13</mn></mtd><mtd/></mtr><mtr><mtd><mo lspace="0" rspace="0">.</mo><mn>25</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>07</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>11</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>09</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>05</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>06</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>05</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>04</mn></mtd><mtd><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>04</mn></mtd><mtd/></mtr><mtr><mtd><mo lspace="0" rspace="0">.</mo><mn>29</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>12</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>10</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>12</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>20</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>01</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>10</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>12</mn></mtd><mtd><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>15</mn></mtd><mtd/></mtr><mtr><mtd><mo lspace="0" rspace="0">.</mo><mn>35</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>02</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>20</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>18</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>11</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>03</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>18</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>21</mn></mtd><mtd><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>13</mn></mtd><mtd/></mtr><mtr><mtd><mo lspace="0" rspace="0">.</mo><mn>38</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>02</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>02</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>00</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>03</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>07</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>00</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>00</mn></mtd><mtd><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>01</mn></mtd><mtd/></mtr><mtr><mtd><mo lspace="0" rspace="0">.</mo><mn>47</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>01</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>05</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>02</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>01</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>12</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>00</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>02</mn></mtd><mtd><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">.</mo><mn>02</mn></mtd><mtd/></mtr><mtr><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd><mo lspace="0" rspace="0">-</mo><mn>1</mn></mtd><mtd><mn>1</mn></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow><mspace width="0.167em"/><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><msub><mi>x</mi><mrow><mi>M</mi><mspace width="0"/><mi>a</mi></mrow></msub></mtd></mtr><mtr><mtd><msub><mi>x</mi><mrow><mi>R</mi><mspace width="0"/><mi>i</mi></mrow></msub></mtd></mtr><mtr><mtd><msub><mi>x</mi><mrow><mi>W</mi><mspace width="0"/><mi>h</mi></mrow></msub></mtd></mtr><mtr><mtd><msub><mi>x</mi><mrow><mi>P</mi><mspace width="0"/><mi>o</mi></mrow></msub></mtd></mtr><mtr><mtd><msub><mi>x</mi><mrow><mi>C</mi><mspace width="0"/><mi>a</mi></mrow></msub></mtd></mtr><mtr><mtd><msub><mi>x</mi><mrow><mi>S</mi><mspace width="0"/><mi>o</mi></mrow></msub></mtd></mtr><mtr><mtd><msub><mi>x</mi><mrow><mi>S</mi><mspace width="0"/><mi>w</mi></mrow></msub></mtd></mtr><mtr><mtd><msub><mi>x</mi><mrow><mi>Y</mi><mspace width="0"/><mi>a</mi></mrow></msub></mtd></mtr><mtr><mtd><msub><mi>x</mi><mrow><mi>S</mi><mspace width="0"/><mi>o</mi></mrow></msub></mtd></mtr><mtr><mtd><msub><mi>x</mi><mrow><mi>P</mi><mspace width="0"/><mi>l</mi></mrow></msub></mtd></mtr><mtr><mtd><msub><mi>x</mi><mi>A</mi></msub></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow><mo lspace="0.278em" rspace="0.278em">≥</mo><mrow><mo stretchy="true">[</mo><mrow><mstyle scriptlevel="0"><mtable><mtr><mtd><mn>0</mn><mo lspace="0" rspace="0">.</mo><mn>068</mn></mtd></mtr><mtr><mtd><mn>0</mn><mo lspace="0" rspace="0">.</mo><mn>051</mn></mtd></mtr><mtr><mtd><mn>0</mn><mo lspace="0" rspace="0">.</mo><mn>020</mn></mtd></mtr><mtr><mtd><mn>0</mn><mo lspace="0" rspace="0">.</mo><mn>055</mn></mtd></mtr><mtr><mtd><mn>0</mn><mo lspace="0" rspace="0">.</mo><mn>256</mn></mtd></mtr><mtr><mtd><mn>0</mn><mo lspace="0" rspace="0">.</mo><mn>109</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd></mtr></mtable></mstyle></mrow><mo stretchy="true">]</mo></mrow></mrow>
</math>
</span></p>
<p>Each column corresponds to a staple crop from maize to plantain and the final column is for optimizing area.
The values are weighted by how much is produced per hectare by the most productive country for each crop.
Rows are scaled so that the values for the ninth column (sorghum) are all ones.
The right-hand side is given by the RDA column in the Wikipedia article and represents how many hectares must be cultivated to produce 10,000 person-days of each nutrient.</p>
<p>Rows correspond to energy, protein, carbohydrates, fiber, monounsaturated fatty acids and polyunsaturated fatty acids.
The final row is the balance equation for area.</p>
<p>We can see by visual inspection that sorghum is the most efficient crop in terms of area, with 0.26 hectares being enough to supply 10,000 person-days of macronutrients.
The limiting factor is monounsaturated fatty acids. If canola oil is used for fat, then the necessary area shrinks to around 0.11 hectares.</p>
<p>This sort of diet would only really be acceptable in the most extreme circumstances.
As I said in the beginning of this section, one would add extra constraints that certain crops should be grown because people want them. Yields also vary by location, but adding extra variables per grid locator for optimization would not fit in a blog post.</p>Cybernetics, politics and sparse linear algebra2021-02-04T12:37:00+01:002021-02-04T12:37:00+01:00tomastag:www.härdin.se,2021-02-04:/blog/2021/02/04/cybernetics-politics-and-sparse-linear-algebra/<p>Time for an uncharacteristically political post. This will also likely be the first in a series of posts. I will link the rest of them here at the start as I finish them.</p>
<p>To see the rest of the posts in this series, click the "cybernetics" tag in the box …</p><p>Time for an uncharacteristically political post. This will also likely be the first in a series of posts. I will link the rest of them here at the start as I finish them.</p>
<p>To see the rest of the posts in this series, click the "cybernetics" tag in the box on the right.
Two paragraphs up if using a text-mode browser.</p>
<h2>The case for planning</h2>
<p>The last few years the climate situation and market economies' inability to address it has caused me to read up on political theory to try and figure out what can be done. I haven't written much about this journey on here, but those who know me know that this process has been going on for quite a while. My conclusion so far is that the old Soviet <a href="https://en.wikipedia.org/wiki/Cybernetics">cyberneticians</a> were on the right track.</p>
<p>This all ties to what is known as the <a href="https://en.wikipedia.org/wiki/Economic_calculation_problem">economic calculation problem</a> (ECP). The debate revolves around whether planning is feasible as a replacement for markets. This debate raged primarily in the interwar years and is one which never had a satisfactory conclusion. Since the dissolution of the USSR between 1989-1991 the debate seemed to have been settled in favor of markets. After the end of the USSR the idea of free market capitalism as the final stage of humankind emerged, what we today know as neoliberalism, the dominant global ideology.</p>
<p>Today neoliberalism faces the challenge of how to address the ongoing climate catastrophe in a way that does not place undue burden on the unelected elite that owns the economy. This gives rise to policies that create tension between the different sections of the working classes. One recent example of this is the <a href="https://en.wikipedia.org/wiki/Yellow_vests_movement">yellow vest movement</a>, triggered by the Macron government's fuel taxes.</p>
<p>One reason for the rise of movements like the yellow vests is the idea that greenhouse gas (GHG) emissions must have a <em>cost</em>. And as we all know, whatever has a fixed cost is effectively free if you're rich, and taxes on consumption like VAT are regressive in practice. Another complication is that people living in cities are less affected by fuel taxes than people living in rural areas, especially up here in northern Sweden where distances are far and most social services have moved to the cities.</p>
<p>The fair and rational solution to the climate situation, which the market system has proven itself unable to deal with, is a global planned economy. I will not concern myself too much with the politics behind the plan in these posts, other than to say that I prefer if the political process is as democratic as possible. It should also be pointed out that the workplaces that most of us spend half our waking time in is by no means democratic. In most private companies all decisions are taken by the company's owners, which are never elected or drawn by lot or any such process. In addition, no company uses a market system internally. Neither do families.</p>
<p>Beyond being more democratic, planning also has the potential to be much more efficient than markets, meaning the same standard of living can be maintained with less labour input. This will be important as humanity transitions from capitalism into a sustainable steady-state economy.</p>
<h2>Why the economic calculation problem is easier than previously thought</h2>
<p>Back in the 1920's up to the 1940's when the ECP debate raged the counterargument to economic planning from people like <a href="https://en.wikipedia.org/wiki/Friedrich_Hayek">Friedrich Hayek</a> was that there is simply no practical way to rationally allocate resources <a href="https://en.wikipedia.org/wiki/Calculation_in_kind">in-natura</a> for an entire economy. If you have say 1000 goods then it would take 1000<sup>3</sup> = one billion operations to solve the related linear equations. So the argument went that a team of humans working with calculators could not hope the finish the calculations within the span of a human lifetime, even for quite modest economies.</p>
<p>To the modern reader there is perhaps an obvious solution to this problem: computers. In the time the ECP debate raged, the term <em>computer</em> was a job title, like professor or plumber. It would take until some time after the second world war for computer science to be properly established. Modern computers can perform billions of calculations per second, cheaply.</p>
<h2>What kind of computations do we need?</h2>
<p>Having realized that computers can plan economic activity, the question become "how much of it?". The answer turns out to be "quite a lot"!</p>
<p><a href="https://en.wikipedia.org/wiki/Wassily_Leontief">Wassily Leontief</a> developed the concept of <em>input-output analysis</em> around <a href="doi:10.2307/1927837">1936</a>. This involves finding the solution to a linear equation system on the form <em>(I - A)x = d</em> where <em>A</em> is a matrix of technical coefficients saying how much of each good is required to produce one unit of some other good, <em>d</em> is a given vector of final demands and <em>x</em> is a vector saying how much of each good to produce, including intermediate goods.
Solving such a system naïvely using Gaussian elimination indeed takes time cubic in the number of variables. But as even Leontief noted, the matrix A has many entries that are zero. A is <em>sparse</em>.</p>
<p>Dealing with sparse matrices is at present a scientific field unto itself. Modern computers routinely solve sparse linear system in tens of millions of variables, and computer clusters can deal with billions of variables. So far so good.</p>
<h2>What's the catch?</h2>
<p>Solving linear systems is unfortunately not enough. In reality there are limitations to how much each industry can produce, how many people can work in each industry, transport limitations, how much GHG may be emitted and so on.
Solving constrained linear systems like this is known as <em>linear programming</em>. LP is a much more difficult problem than just solving a linear equation. So much more difficult that finding an optimal solution is suspected to take time <em>exponential</em> in the number of variables, not cubic. Not good!</p>
<h2>How do we solve LP in reasonable time then?</h2>
<p>The key to using LP for economic planning is realizing that we don't need an optimal solution. An approximate solution works just as well, provided it's known to be close enough to the optimum, say within 1%.
There is a whole class of <a href="https://en.wikipedia.org/wiki/Linear_programming#Algorithms">algorithms</a> that can do this.
The following table is a summary with simplified <a href="https://en.wikipedia.org/wiki/Big_O_notation">big-O notation</a>:</p>
<table>
<tr>
<th>Who</th>
<th>When</th>
<th>Complexity</th>
<th>Worst case</th>
</tr>
<tr>
<td>Khachiyan</td>
<td>1979</td>
<td>O(n<sup>6</sup>L)</td>
<td>O(n<sup>6</sup>L)</td>
</tr>
<tr>
<td>Karmarkar</td>
<td>1984</td>
<td>O(n<sup>3.5</sup>L)</td>
<td>O(n<sup>3.5</sup>L)</td>
</tr>
<tr>
<td>Renegar</td>
<td>1988</td>
<td>O(d<sup><abbr title="ω ≃ 2.373 is the matrix multiplication constant">2.373</abbr></sup>n<sup>0.5</sup>L)</td>
<td>O(n<sup>2.873</sup>L)</td>
</tr>
<tr>
<td>Vaidya</td>
<td>1989</td>
<td>O((n+d)<sup>1.5</sup>nL)</td>
<td>O(n<sup>2.5</sup>L)</td>
</tr>
<tr>
<td>Lee and Sidford</td>
<td>2015</td>
<td>O((nnz(A) + n<sup>2</sup>)n<sup>0.5</sup>L)</td>
<td>O(n<sup>2.5</sup>L)</td>
</tr>
<tr>
<td>Cohen, Lee and Song</td>
<td>2020</td>
<td>O(n<sup><abbr title="Assuming ω does not improve much">2.373</abbr></sup>L)</td>
<td>O(n<sup>2.373</sup>L)</td>
</tr>
</table>
<p><em>nnz(A)</em> is the number of non-zero elements in <em>A</em>, <em>d</em> is the number of variables, <em>n</em> is the number of constraints, <em>d < n</em>.
<em>L</em> is the desired accuracy of the solution, in bits.</p>
<p>In practice many of these algorithms are slower since matrix multiplication is O(n<sup>2.8</sup>) for <em>n</em> that modern computers can actually handle. For a real economy <em>n</em> will be on the order of 10<sup>9</sup>, which still makes the computations impractical <em>if run on a single computer</em>. There is a need to evaluate how well LP can be solved on computer clusters, especially as the number of nodes <em>N</em> approaches <em>√n</em>, <em>n</em> or even <em>nnz(A)</em>. The notion here is that every workplace could have a computer that participates in the planning process, or perhaps a computer cluster per city, all connected over the internet.
The more nodes that are connected together, the more efficient the economy becomes.</p>
<p>In a future post I will go into detail on my findings what algorithms seem suitable for parallelization, and some experimental results.</p>
<h2>Other considerations</h2>
<p>The ideas in this section are mostly taken from <a href="https://arxiv.org/pdf/2005.01539.pdf">this paper from 2020 by Spyridon Samothrakis</a>.</p>
<p>Real economies are not linear. There are synergies, overhead, depreciation and diminishing returns.
The following plot illustrates how the requirements for a section of the chemical industry might depend on how much of its output is called for:</p>
<p><img style="display:block;width:50%;margin-left:auto;margin-right:auto;" src="http://www.härdin.se/images/sector.png" alt="Plot demonstrating behaviour of some sector"/></p>
<!-- The Octave code for this plot is:
x=(2:0.1:102)'; y=[log(x), (x-min(x))*0.05, 2.5*ones(size(x))]; x-=min(x); plot(x,y(:,1),x,y(:,2),x,y(:,3)); axis([0,max(x),0,5]); legend('labour','raw materials','catalyst'); xlabel('Output requested'); ylabel('Inputs required'); title('Behaviour of some sector');
-->
<p>The line for raw materials demonstrates the kind of linear model that Leontief assumes.
The labour curve demonstrates how larger-scale production might reduce the marginal labour requirements in some sector, and that small-scale production often results in mediocre output. The labour curve is also non-zero for no output, which models how some industries will have overhead inherent from just sitting around.
Finally the catalyst curve is for demonstrating that there may be inputs that change very little regardless of demand.</p>
<p>This sort of non-linear behavior may be wildly different between sectors. In principle it can be captured by piecewise linearization. Another option is to move toward either quadratic programming (QP) or general <a href="https://en.wikipedia.org/wiki/Mathematical_programming">mathematical programming</a>.</p>
<h2>Further reading</h2>
<p>For an overview of how a society based around computerized planning might work, I recommend reading <a href="http://ricardo.ecn.wfu.edu/~cottrell/socialism_book/new_socialism.pdf">Towards a New Socialism</a> by <a href="http://paulcockshott.co.uk/">Paul Cockshott</a> and <a href="https://users.wfu.edu/cottrell/">Allin Cottrell</a>.</p>
<p>Other related reads:</p>
<ul>
<li><a href="https://www.goodreads.com/book/show/38914131-the-people-s-republic-of-walmart">The People's Republic of Walmart</a> by Leigh Phillips and Michal Rozworski</li>
<li><a href="https://press.uchicago.edu/ucp/books/book/chicago/C/bo8169881.html">The Cybernetic Brain</a> by Andrew Pickering</li>
<li><a href="https://www.goodreads.com/book/show/1304488.Brain_of_the_Firm">Brain of the Firm</a> by Stafford Beer</li>
</ul>
<p>Some names of people in this field in no particular order:</p>
<ul>
<li><a href="https://en.wikipedia.org/wiki/Wassily_Leontief">Wassily Leontief</a></li>
<li><a href="https://en.wikipedia.org/wiki/Leonid_Kantorovich">Leonid Kantorovich</a></li>
<li><a href="https://en.wikipedia.org/wiki/Victor_Glushkov">Victor Glushkov</a></li>
<li><a href="https://en.wikipedia.org/wiki/Stafford_Beer">Stafford Beer</a></li>
<li><a href="https://en.wikipedia.org/wiki/Otto_Neurath">Otto Neurath</a></li>
</ul>
<p>For those who prefer podcasts I can recommend <a href="http://generalintellectunit.net/">General Intellect Unit</a> which should be available wherever you get your podcasts.</p>Marshall Stockwell teardown2020-08-30T20:07:32+02:002020-08-30T20:07:32+02:00tomastag:www.härdin.se,2020-08-30:/blog/2020/08/30/marshall-stockwell-teardown/<p>Yesterday a friend of mine gave me his Marshall Stockwell wireless audio player/amplifier to try to debug and fix.
The battery in it would take a charge, and the charging LED would pulse, but the unit itself wouldn't start.</p>
<p>Taking the unit apart and removing the small PCB covering …</p><p>Yesterday a friend of mine gave me his Marshall Stockwell wireless audio player/amplifier to try to debug and fix.
The battery in it would take a charge, and the charging LED would pulse, but the unit itself wouldn't start.</p>
<p>Taking the unit apart and removing the small PCB covering the top left portion of the main PCB, we are greeted with this:</p>
<p><a href="http://www.härdin.se/images/marshall_stockwell/P8302046.JPG"><img alt="Picture of the main PCB in the Marshall Stockwell" src="http://www.härdin.se/images/marshall_stockwell/tP8302046.JPG"></a></p>
<p>Different lighting:</p>
<p><a href="http://www.härdin.se/images/marshall_stockwell/P8302049.JPG"><img alt="Another picture of the same PCB, with different lighting" src="http://www.härdin.se/images/marshall_stockwell/tP8302049.JPG"></a></p>
<p>The two wires and the through-hole resistor are bodges of mine done during testing.
I also had to snip the IC to the right of the red bodge wire, which was the 3.3V DC/DC regulator.</p>
<p>Some initial measurements showed that the 5V rail was dead and that Q4, the P-channel MOSFET that enables the 15V supply for the rest of the unit, would not turn on.
Some time during my investigations the 3.3V switching power supply also broke.</p>
<p>Q4 was easy enough to turn on, just a 10k resistor from its gate to ground.
I hooked up an external power supply for the 3.3V rail and let the unit run for a while.</p>
<p>After some time had passed, I noticed the current draw on the 3.3V rail went from 500 mA down to around 400 mA.
Most of this current was going to a single 5.8 Ohm resistor, R25, which appears to be connected to a diode elsewhere.
Unsoldering one of R25's legs reduced the current to around 80 mA, much more reasonable.</p>
<p>Despite turning on Q4 and feeding the 3.3V rail the 5V regulator would not turn on.
The pin on U2 which I suspect to be the "enable" pin measured 0V.
The "input" LED would however light up.</p>
<p>I have some more tricks up my sleeve to try and resurrect this thing.
For now hopes are slim.</p>
<h2>Reverse-engineering</h2>
<p>The board revision is "Stockwell V.A2 160630".</p>
<p>I have summarized what components I have identified on the board in the hopes that it might be useful for someone in the future:</p>
<table style="width:100%">
<tr>
<th>Ref</th>
<th>Markings</th>
<th>Part name</th>
<th>Function</th>
<th>Links</th>
</tr>
<tr>
<td>?</td>
<td>MP26123</td>
<td>MP26123</td>
<td>2A,24V Input, 600kHz 2/3-Cell Switching Li-ion Battery Charger</td>
<td><a href="https://www.monolithicpower.com/en/documentview/productdocument/index/version/2/document_type/Datasheet/lang/en/sku/MP26123/document_id/1398">datasheet</a></td>
</tr>
<tr>
<td>Q4</td>
<td>ME50P06-6</td>
<td>ME50P06-6</td>
<td>P-Channel Power MOSFET</td>
<td><a href="https://www.onsemi.com/pub/Collateral/MTB50P03HDL-D.PDF">datasheet</a></td>
</tr>
<tr>
<td>?</td>
<td>NTP-8230</td>
<td>NTP-8230</td>
<td>High Performance, High Fidelity Power Driver Integrated Full Digital Audio Amplifier</td>
<td><a href="https://cdn.datasheetspdf.com/pdf-down/N/T/P/NTP-8230_NeoFidelity.pdf">datasheet</a></td>
</tr>
<tr>
<td>U3</td>
<td>YJ33</td>
<td>SGM2019</td>
<td>3.3V linear regulator for audio</td>
<td><a href="http://datasheet.elcodis.com/pdf2/98/61/986187/sgm2019-2.9yn5g-tr.pdf">datasheet</a></td>
</tr>
<tr>
<td>U4</td>
<td>PCM1808</td>
<td>PCM1808</td>
<td>Single-Ended, Analog-Input 24-Bit, 96-kHz Stereo ADC</td>
<td><a href="https://www.ti.com/lit/ds/symlink/pcm1808.pdf">datasheet</a></td>
</tr>
<tr>
<td>U2</td>
<td>04=34P (hard to read)</td>
<td>LM2734Z/-Q1 (qualified guess)</td>
<td>5V DC/DC for USB</td>
<td><a href="https://www.ti.com/lit/ds/symlink/lm2734z-q1.pdf">datasheet</a></td>
</tr>
<tr>
<td>?</td>
<td>TPS5401</td>
<td>TPS5401</td>
<td>3.3V DC/DC</td>
<td><a href="https://www.ti.com/lit/ds/symlink/tps5401.pdf">datasheet</a></td>
</tr>
<tr>
<td>U5</td>
<td>N79E814AT28</td>
<td>N79E814AT28</td>
<td>8051 clone</td>
<td><a href="https://www.nuvoton.com/products/microcontrollers/8bit-8051-mcus/low-pin-count-8051-series/n79e814/?__locale=en">product page</a>,
<a href="https://www.nuvoton.com/export/resource-files/UM_NuTiny-SDK-N79E715_EN_Rev2.01.pdf">user manual</a>
</td>
</tr>
<tr>
<td>U1</td>
<td>HEF4052BT<br/>
CKZ63107</td>
<td>HEF4052BT</td>
<td>2-channel 4-to-1 analog mux</td>
<td><a href="https://assets.nexperia.com/documents/data-sheet/HEF4052B_Q100.pdf">datasheet</a></td>
</tr>
<tr>
<td>U14</td>
<td>4560<br/>
U014S<br/>
JRC</td>
<td>NJM4560</td>
<td>Dual Operational Amplifier</td>
<td><a href="https://static.chipdip.ru/lib/235/DOC000235287.pdf">datasheet</a></td>
</tr>
</table>
<p>The unit has two 3.3V supplies: one linear, connected to all analog audio chips, and one switching, connected to the logic, buttons and potentiometers.</p>leftpad() proved in Frama-C2020-03-22T19:15:24+01:002020-03-22T19:15:24+01:00tomastag:www.härdin.se,2020-03-22:/blog/2020/03/22/leftpad-proved-in-frama-c/<p>Last Friday I found the <a href="https://github.com/hwayne/lets-prove-leftpad">lets-prove-leftpad</a>
repository on GitHub.
The idea is to prove <code>leftpad</code>, a function that pads a string with a given character <code>c</code>,
up to a given length <code>n</code>.</p>
<p><code>leftpad</code> is notorious for being its own NPM package.
The owner of the <code>leftpad</code> package decided to take …</p><p>Last Friday I found the <a href="https://github.com/hwayne/lets-prove-leftpad">lets-prove-leftpad</a>
repository on GitHub.
The idea is to prove <code>leftpad</code>, a function that pads a string with a given character <code>c</code>,
up to a given length <code>n</code>.</p>
<p><code>leftpad</code> is notorious for being its own NPM package.
The owner of the <code>leftpad</code> package decided to take it down,
taking thousands of projects with it that had it as a dependency.
<a href="https://www.theregister.co.uk/2016/03/23/npm_left_pad_chaos/">This article</a>
on The Register has more details.</p>
<p>There was no example in lets-prove-leftpad using ACSL or Frama-C,
so I decided to give that a shot.
My work resulted in <a href="https://github.com/hwayne/lets-prove-leftpad/pull/33">this pull request</a>,
which was merged shortly after.
I have quoted both the implementation and the associated readme below.</p>
<h2>leftpad.c</h2>
<div class="highlight"><pre><span></span><code><span class="cp">#include</span><span class="w"> </span><span class="cpf"><string.h></span>
<span class="cm">/*@ requires \valid(s + (0..n));</span>
<span class="cm"> requires valid_string(s);</span>
<span class="cm"> requires c != 0;</span>
<span class="cm"> behavior no_padding:</span>
<span class="cm"> assumes strlen(s) >= n;</span>
<span class="cm"> assigns \nothing;</span>
<span class="cm"> behavior padding:</span>
<span class="cm"> assumes strlen(s) < n;</span>
<span class="cm"> ensures valid_string(s);</span>
<span class="cm"> ensures \let l = strlen{Pre}(s); \let p = n - l;</span>
<span class="cm"> (\forall integer x; 0 <= x < p ==> s[x] == c) &&</span>
<span class="cm"> memcmp{Pre, Post}(s, s + p, l + 1) == 0 &&</span>
<span class="cm"> strlen(s) == n;</span>
<span class="cm"> assigns s[0 .. n];</span>
<span class="cm"> complete behaviors;</span>
<span class="cm"> disjoint behaviors;</span>
<span class="cm"> */</span>
<span class="kt">void</span><span class="w"> </span><span class="nf">leftpad</span><span class="p">(</span><span class="kt">char</span><span class="w"> </span><span class="n">c</span><span class="p">,</span><span class="w"> </span><span class="kt">size_t</span><span class="w"> </span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">s</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">size_t</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">strlen</span><span class="p">(</span><span class="n">s</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">n</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="n">l</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">size_t</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">l</span><span class="p">;</span>
<span class="w"> </span><span class="c1">// This loop is equivalent to memmove(s+p, s, l+1)</span>
<span class="w"> </span><span class="cm">/*@ loop invariant x_range: 0 <= x <= l;</span>
<span class="cm"> loop invariant s_state: \forall integer i; 0 <= i <= n ==></span>
<span class="cm"> (i <= x+p ==> s[i] == \at(s[i], LoopEntry)) &&</span>
<span class="cm"> (i > x+p ==> s[i] == \at(s[i-p], LoopEntry));</span>
<span class="cm"> loop assigns x, s[p..n];</span>
<span class="cm"> loop variant x;</span>
<span class="cm"> */</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">size_t</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">l</span><span class="p">;;</span><span class="w"> </span><span class="n">x</span><span class="o">--</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">s</span><span class="p">[</span><span class="n">x</span><span class="o">+</span><span class="n">p</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">s</span><span class="p">[</span><span class="n">x</span><span class="p">];</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">break</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="c1">// These assertions are not strictly necessary, but they speed up the verification</span>
<span class="w"> </span><span class="c1">//@ assert same_chars: memcmp{Pre, Here}(s, s+p, l+1) == 0 && s[n] == 0;</span>
<span class="w"> </span><span class="c1">//@ assert valid_str: valid_string(s+p);</span>
<span class="w"> </span><span class="c1">//@ assert same_len: strlen(s+p) == l;</span>
<span class="w"> </span><span class="c1">// This loop is equivalent to memset(s, c, p)</span>
<span class="w"> </span><span class="cm">/*@ loop invariant x_range2: 0 <= x <= p;</span>
<span class="cm"> loop invariant still_same: memcmp{Pre, LoopCurrent}(s, s+p, l+1) == 0 && s[n] == 0;</span>
<span class="cm"> loop invariant valid_grows: valid_string(s + p - x);</span>
<span class="cm"> loop invariant padding_grows: \forall integer i; p - x <= i < p ==> s[i] == c;</span>
<span class="cm"> loop assigns x, s[0..p-1];</span>
<span class="cm"> loop variant p - x;</span>
<span class="cm"> */</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">size_t</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">p</span><span class="p">;</span><span class="w"> </span><span class="n">x</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">s</span><span class="p">[</span><span class="n">p</span><span class="mi">-1</span><span class="o">-</span><span class="n">x</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">c</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
<h2>readme.md</h2>
<h3>About Frama-C</h3>
<p>From the Frama-C website:</p>
<blockquote>
<p>Frama-C is an extensible and collaborative platform dedicated to source-code analysis of C software.</p>
</blockquote>
<p>In other words, Frama-C is a set of tools for analysing C programs.
Most relevant for this example is the Weakest Precondition plugin (<code>-wp</code>),
which uses <a href="https://en.wikipedia.org/wiki/Predicate_transformer_semantics">weakest precondition calculus</a>
to prove <a href="https://en.wikipedia.org/wiki/ANSI/ISO_C_Specification_Language">ANSI/ISO C Specification Language</a> (ACSL) annotations in C programs.</p>
<p>ACSL is based on the <a href="https://en.wikipedia.org/wiki/Java_Modeling_Language">Java Modeling Language</a> (JML),
so the annotations are quite similar to the Java example in this repository.</p>
<p>Debian ships with some rather old versions of Frama-C (14.0 Silicon and 16.0 Sulfur vs 20.0 Calcium),
so I would recommend using the latest version which can be installed via <a href="https://opam.ocaml.org/">opam</a>.</p>
<h3>About this proof</h3>
<p>This example proves an in-place variant of <code>leftpad</code> implemented using loops.
The latest version of Frama-C is used, version 20.0 (Calcium).
An example invocation looks like this:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>frama-c<span class="w"> </span>-wp<span class="w"> </span>-wp-rte<span class="w"> </span>-warn-unsigned-overflow<span class="w"> </span>leftpad.c
<span class="o">[</span>kernel<span class="o">]</span><span class="w"> </span>Parsing<span class="w"> </span>leftpad.c<span class="w"> </span><span class="o">(</span>with<span class="w"> </span>preprocessing<span class="o">)</span>
<span class="o">[</span>rte<span class="o">]</span><span class="w"> </span>annotating<span class="w"> </span><span class="k">function</span><span class="w"> </span>leftpad
<span class="o">[</span>wp<span class="o">]</span><span class="w"> </span><span class="m">56</span><span class="w"> </span>goals<span class="w"> </span>scheduled
<span class="o">[</span>wp<span class="o">]</span><span class="w"> </span><span class="o">[</span>Cache<span class="o">]</span><span class="w"> </span>found:31
<span class="o">[</span>wp<span class="o">]</span><span class="w"> </span>Proved<span class="w"> </span>goals:<span class="w"> </span><span class="m">56</span><span class="w"> </span>/<span class="w"> </span><span class="m">56</span>
<span class="w"> </span>Qed:<span class="w"> </span><span class="m">25</span><span class="w"> </span><span class="o">(</span>2ms-26ms-88ms<span class="o">)</span>
<span class="w"> </span>Alt-Ergo<span class="w"> </span><span class="m">2</span>.3.0:<span class="w"> </span><span class="m">31</span><span class="w"> </span><span class="o">(</span>23ms-306ms-3.8s<span class="o">)</span><span class="w"> </span><span class="o">(</span><span class="m">2273</span><span class="o">)</span><span class="w"> </span><span class="o">(</span>cached:<span class="w"> </span><span class="m">31</span><span class="o">)</span>
</code></pre></div>
<p>The option <code>-wp</code> enables the Weakest Precondition plugin (WP).
<code>-wp-rte</code> tells WP to insert checks for run-time exceptions,
which is Frama-C parlance for undefined behavior (UB)
such as signed overflow or out-of-bounds memory access.
<code>-warn-unsigned-overflow</code> inserts checks for unsigned overflow,
which <em>are</em> defined in C, but since our loop variables are <code>size_t</code> we want checks that they don't overflow.</p>
<p>The output of the program tells us that all goals were proved.
Some of the proof obligations could be trivially discharged by Frama-C's built-in checker <code>Qed</code>.
The rest were verified by <a href="https://alt-ergo.ocamlpro.com/">Alt-Ergo</a>.
On my machine (Intel(R) Core(TM) i5-3317U CPU @ 1.70GHz) this takes just over 7.8 seconds to run.</p>
<p>If you have <code>frama-c-gui</code> installed, it can be invoked similarly by just replacing the name of the program:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>frama-c-gui<span class="w"> </span>-wp<span class="w"> </span>-wp-rte<span class="w"> </span>-warn-unsigned-overflow<span class="w"> </span>leftpad.c
</code></pre></div>
<p>The GUI is used to assist the provers in a semi-automatic fashion, and is outside the scope of this example.</p>
<p>Frama-C uses <a href="http://why3.lri.fr/">Why3</a> to interface with the provers,
and usually ships with Alt-Ergo as its default prover.</p>
<h4>Contract</h4>
<p>First of all we'll take a look at the contract of the function:</p>
<div class="highlight"><pre><span></span><code><span class="cm">/*@ requires \valid(s + (0..n));</span>
<span class="cm"> requires valid_string(s);</span>
<span class="cm"> requires c != 0;</span>
<span class="cm"> behavior no_padding:</span>
<span class="cm"> assumes strlen(s) >= n;</span>
<span class="cm"> assigns \nothing;</span>
<span class="cm"> behavior padding:</span>
<span class="cm"> assumes strlen(s) < n;</span>
<span class="cm"> ensures valid_string(s);</span>
<span class="cm"> ensures \let l = strlen{Pre}(s); \let p = n - l;</span>
<span class="cm"> \forall integer x; 0 <= x < p ==> s[x] == c &&</span>
<span class="cm"> memcmp{Pre, Post}(s, s + p, l + 1) == 0 &&</span>
<span class="cm"> strlen(s) == n;</span>
<span class="cm"> assigns s[0 .. n];</span>
<span class="cm"> complete behaviors;</span>
<span class="cm"> disjoint behaviors;</span>
<span class="cm"> */</span>
<span class="kt">void</span><span class="w"> </span><span class="nf">leftpad</span><span class="p">(</span><span class="kt">char</span><span class="w"> </span><span class="n">c</span><span class="p">,</span><span class="w"> </span><span class="kt">size_t</span><span class="w"> </span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">s</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
</code></pre></div>
<p>The <code>requires</code> clauses are our preconditions.
They say that we need <code>s</code> to have space for <code>n+1</code> characters,
that <code>s</code> must be a valid string and that the padding character cannot be NUL.
<code>valid_string</code> is a predicate defined internally in Frama-C in the file <code>__fc_string_axiomatic.h</code>:</p>
<div class="highlight"><pre><span></span><code><span class="cm">/*@ predicate valid_string{L}(char *s) =</span>
<span class="cm"> @ 0 <= strlen(s) && \valid(s+(0..strlen(s)));</span>
</code></pre></div>
<p><code>strlen</code> in turn has an axiomatic definition in the same file which is too lengthy to quote here.
After the preconditions we have two so-called <code>behaviors</code>: <code>no_padding</code> and <code>padding</code>.</p>
<p><code>no_padding</code> says that if the length of <code>s</code> is <code>n</code> or more then the function assigns nothing,
meaning the function has no side-effects.
This implicitly means that the length and contents of <code>s</code> remain unchanged.</p>
<p>The <code>padding</code> behavior says that if the length of <code>s</code> is less than <code>n</code> then <code>s</code> will be padded.
The two <code>ensures</code> clauses that follow are postconditions that specify what this means.
<code>valid_string(s)</code> means that the resulting <code>s</code> will be a valid string, just as in the preconditions.
The second clause defines the contents of <code>s</code>.
It defines two local names using <code>\let</code>, for readability:
one for the length of the input string (<code>l</code>) and another the amount of padding (<code>p</code>).
The <code>{Pre}</code> in the <code>strlen</code> predicate specifies that it is the length of <code>s</code> <em>when the function is called</em>,
not <em>after</em> it has been called. The latter would be <code>strlen(s)</code> or <code>strlen{Post}(s)</code>.
Let us take a closer look at the conjunction that makes up the rest of this postcondition:</p>
<p><code>(\forall integer x; 0 <= x < p ==> s[x] == c)</code>
says that the first <code>p</code> characters in <code>s</code> are <code>c</code>.
<code>memcmp{Pre, Post}(s, s + p, l + 1) == 0</code> uses the logic function <code>memcmp</code> to say that
the contents of <code>s</code> at offset <code>p</code> is the same as the input string, including the NUL terminator.
<code>memcmp</code> is defined axiomatically in <code>__fc_string_axiomatic.h</code>:</p>
<div class="highlight"><pre><span></span><code><span class="cm">/*@ axiomatic MemCmp {</span>
<span class="cm"> @ logic ℤ memcmp{L1,L2}(char *s1, char *s2, ℤ n)</span>
<span class="cm"> @ reads \at(s1[0..n - 1],L1), \at(s2[0..n - 1],L2);</span>
<span class="cm"> @</span>
<span class="cm"> @ axiom memcmp_zero{L1,L2}:</span>
<span class="cm"> @ \forall char *s1, *s2; \forall ℤ n;</span>
<span class="cm"> @ memcmp{L1,L2}(s1,s2,n) == 0</span>
<span class="cm"> @ <==> \forall ℤ i; 0 <= i < n ==> \at(s1[i],L1) == \at(s2[i],L2);</span>
<span class="cm"> @</span>
<span class="cm"> @ }</span>
<span class="cm"> @*/</span>
</code></pre></div>
<p>This definition only covers the <code>memcmp() == 0</code> case, but this is enough for our purposes.
There is a <code>strcmp</code> predicate which could be useful here,
but it sadly cannot compare strings at different labels in Calcium.
A not-in-place implementation of <code>leftpad</code> could make use of the <code>strcmp</code> predicate however.</p>
<p>Finally we have <code>strlen(s) == n</code> which says that the resulting string is of length <code>n</code>,
which implies that there are no NUL characters in the range <code>s[0..n-1]</code>.</p>
<p>The final <code>assigns</code> clause says that the <code>padding</code> behavior
has the side effect of assigning elements in the range <code>s[0..n]</code>.
In general it is possible that the function assigns only a subset of this range;
<code>assigns</code> is allowed to specify a superset of the elements actually assigned.</p>
<p>The final two lines in the contract specify that the <code>assumes</code> clauses cover the entire behavior of the function.
Specifically, the combination of <code>complete behaviors</code> and <code>disjoint behaviors</code> means that the preconditions imply
<code>strlen(s) >= n</code> XOR <code>strlen(s) < n</code>.
For more information about behaviors, see the ACSL manual on the Frama-C website.</p>
<h4>Implementation</h4>
<p>The implementation makes use of two loops,
which are only executed if the length of the input string is less than <code>n</code>.
The first loop is equivalent to <code>memmove(s+p, s, l+1)</code> and the second loop to <code>memset(s, c, p)</code>.
Let us look closer at the first loop:</p>
<div class="highlight"><pre><span></span><code><span class="cm">/*@ loop invariant x_range: 0 <= x <= l;</span>
<span class="cm"> loop invariant s_state: \forall integer i; 0 <= i <= n ==></span>
<span class="cm"> (i <= x+p ==> s[i] == \at(s[i], LoopEntry)) &&</span>
<span class="cm"> (i > x+p ==> s[i] == \at(s[i-p], LoopEntry));</span>
<span class="cm"> loop assigns x, s[p..n];</span>
<span class="cm"> loop variant x;</span>
<span class="cm"> */</span>
<span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">size_t</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">l</span><span class="p">;;</span><span class="w"> </span><span class="n">x</span><span class="o">--</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">s</span><span class="p">[</span><span class="n">x</span><span class="o">+</span><span class="n">p</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">s</span><span class="p">[</span><span class="n">x</span><span class="p">];</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">break</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
<p>This loop moves the string <code>p</code> elements to the right by starting
at the end of the string and makings its way back to <code>p</code> elements from the start.
The loop invariant <code>x_range</code> constrains the range of <code>x</code>.
The invariant <code>s_state</code> describes the contents of <code>s</code> at each iteration in the loop.
The <code>loop assigns</code> describes the side effects of the loop,
namely assigning the loop variable and the elements of <code>s</code> that the loop moves the string into.
To avoid underflowing <code>x</code> an explicit check against zero terminates the loop.
Using <code>ssize_t</code> for <code>x</code> would be an alternative solution.
The loop variant specifies that the loop terminates.
We will go into more detail about loop variants further down.</p>
<p>Between the loops there are three assertions:</p>
<div class="highlight"><pre><span></span><code><span class="c1">//@ assert same_chars: memcmp{Pre, Here}(s, s+p, l+1) == 0 && s[n] == 0;</span>
<span class="c1">//@ assert valid_str: valid_string(s+p);</span>
<span class="c1">//@ assert same_len: strlen(s+p) == l;</span>
</code></pre></div>
<p>The purpose of these is to speed up the verification.
Try removing them and see how it impacts the time spent by <code>frama-c</code>.</p>
<p>The final loop inserts the padding characters at the start of the string:</p>
<div class="highlight"><pre><span></span><code><span class="cm">/*@ loop invariant x_range2: 0 <= x <= p;</span>
<span class="cm"> loop invariant still_same: memcmp{Pre, LoopCurrent}(s, s+p, l+1) == 0 && s[n] == 0;</span>
<span class="cm"> loop invariant valid_grows: valid_string(s + p - x);</span>
<span class="cm"> loop invariant padding_grows: \forall integer i; p - x <= i < p ==> s[i] == c;</span>
<span class="cm"> loop assigns x, s[0..p-1];</span>
<span class="cm"> loop variant p - x;</span>
<span class="cm"> */</span>
<span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">size_t</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">p</span><span class="p">;</span><span class="w"> </span><span class="n">x</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">s</span><span class="p">[</span><span class="n">p</span><span class="mi">-1</span><span class="o">-</span><span class="n">x</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">c</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p><code>x_range2</code> is similar to <code>x_range</code>.
<code>still_same</code> affirms that the loop does not modify the range <code>s[p..n]</code>.
It should not be necessary, but waiting for Alt-Ergo to figure that out would take ages.
It is possible that enabling other provers such as <a href="https://en.wikipedia.org/wiki/Z3_Theorem_Prover">Z3</a> (<code>-wp-prover z3</code>)
might make <code>still_same</code> redundant.
Feel free to experiment!</p>
<p><code>valid_grows</code> says that the valid string grows at each iteration of the loop.
<code>padding_grows</code> similarly says that the padding grows each iteration.
Side effects are similar to the previous loop.
Finally we come to the loop variant.</p>
<p>A loop variant in ACSL is an expression which is positive while the loop is executing,
decreases at each iteration of the loop and becomes zero or less when the loop terminates.
This allows Frama-C to reason about program termination.
Support for verifying program complexity and termination is not supported in Frama-C at the moment (in Calcium).</p>
<h4>A few notes about builtins</h4>
<p>It is possible to implement <code>leftpad</code> using <code>memmove</code> and <code>memset</code>.
Doing so requires the <code>-builtin</code> plugin, which is only available in the development version of Frama-C.
It will be available in the next version of Frama-C, Scandium.
It may also require some "handholding" of the provers via so-called <em>proof scripts</em> generated by the GUI.</p>
<h4>Resources</h4>
<ul>
<li><a href="https://frama-c.com/download/acsl-tutorial.pdf">ACSL Mini-Tutorial</a></li>
<li><a href="https://frama-c.com/download/acsl-implementation-20.0-Calcium.pdf">ACSL 1.14</a></li>
<li><a href="https://frama-c.com/download/wp-manual-20.0-Calcium.pdf">WP manual</a></li>
<li><a href="http://stackoverflow.com/tags/frama-c/">frama-c tag on Stack Overflow</a></li>
<li><a href="http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/frama-c-discuss">Frama-c-discuss mailing list at inria.fr</a></li>
</ul>Hacking in to an Archer MR200 router for fun and profit2019-11-11T15:23:46+01:002019-11-11T15:23:46+01:00tomastag:www.härdin.se,2019-11-11:/blog/2019/11/11/hacking-in-to-an-archer-mr200-router-for-fun-and-profit/<p>I recently bought myself a TP-Link Archer MR200 V4 router and a 4G SIM card with a few GB of data on it and an expiration date of one year.
The reason for this is to allow myself to control some radio gear which I've installed on my property/remote …</p><p>I recently bought myself a TP-Link Archer MR200 V4 router and a 4G SIM card with a few GB of data on it and an expiration date of one year.
The reason for this is to allow myself to control some radio gear which I've installed on my property/remote QTH.</p>
<p>I need to keep an eye on how much data the modem is using so that I don't unexpectedly lose contact with my remote rig. I can't get to it during the winter part of the year since the access road tends to get covered with up to two meters of snow. I am also unsure whether I can refill the SIM card from another phone.
This is a problem shared by similar QTHs around <a href="https://en.wikipedia.org/wiki/Norrland">Norrland</a>.</p>
<p>The amount of data used is readily visible after logging in on the router with a web browser.
Curiously, JavaScript needs to be enabled to do this, not just cookies.
This was the first warning bell.</p>
<p>Thinking it might still be possible to submit the login form manually,
I took a look at the HTML on the login page,
discovering that the login button is not actually part of any form 😑
Many POST requests were also being performed before, during and after login.
POST requests were also performed to get the actual statistics.
Not promising..</p>
<p>Clicking the login button (<code><button id="pc-login-btn"></code>)
causes a loginSubmit() JS function to be called.
This function is part of some minified inline JS,
which I promptly prettified.
loginSubmit() in turn calls doLogin(), with some rather curious parameters:</p>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">rsaEncrypt</span><span class="p">(</span><span class="nx">$</span><span class="p">.</span><span class="nx">Base64Encoding</span><span class="p">(</span><span class="nx">l</span><span class="p">),</span><span class="w"> </span><span class="nx">n</span><span class="p">,</span><span class="w"> </span><span class="nx">e</span><span class="p">),</span>
<span class="w"> </span><span class="nx">doLogin</span><span class="p">(</span><span class="nx">INCLUDE_LOGIN_USERNAME</span><span class="w"> </span><span class="o">?</span>
<span class="w"> </span><span class="nx">rsaEncrypt</span><span class="p">(</span><span class="nx">s</span><span class="p">,</span><span class="w"> </span><span class="nx">n</span><span class="p">,</span><span class="w"> </span><span class="nx">e</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="nx">rsaEncrypt</span><span class="p">(</span><span class="s2">"admin"</span><span class="p">,</span><span class="w"> </span><span class="nx">n</span><span class="p">,</span><span class="w"> </span><span class="nx">e</span><span class="p">),</span>
<span class="w"> </span><span class="nx">t</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="nx">o</span><span class="p">,</span><span class="w"> </span><span class="nx">o</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="nx">$</span><span class="p">(</span><span class="s2">"#ph-login-btn"</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="nx">$</span><span class="p">(</span><span class="s2">"#pc-login-btn"</span><span class="p">))</span>
</code></pre></div>
<p>Great, so not just a regular login form, but one that uses <a href="https://en.wikipedia.org/wiki/RSA_(cryptosystem)">RSA</a> encrypted usernames and passwords..
It turned out however that one can reuse the same username and password RSA pairs,
but only until the device is rebooted.
In other words, I'd either have to spin up a headless web browser (say <code>firefoxdriver</code> or <code>chromium-driver</code>),
or implement RSA somehow 😣</p>
<p>Since I have developed a possibly unhealthy disdain for anything that requires a browser to function,
I decided to go with the latter option.
Luckily the MR200 already ships with an RSA implementation called encrypt.js.
To see if using it was even feasible, I prettified it and ran it through <a href="https://www.mozilla.org/rhino">Rhino</a>.
Unsurprisingly it complained about the variables "jQuery", "navigator" and "window" not existing.
Simply doing <code>var jQuery = Object();</code> before loading encrypt.js took care of the first one,
and commenting out any code having to do with browser stuff worked as well.
This resulted in a file I've called <code>encrypt-stripped.js</code> (see appendix).
After this I was able to use <code>rsaEncrypt()</code> to create username/password pairs with which I could successfully log in. Woo!</p>
<p>There's some other things going on in the login and statistics stuff, which isn't as interesting.
I've summarized the entire login + stats process below:</p>
<ul>
<li>The user navigates to http://192.168.1.1, performing a GET request</li>
<li>The page makes a POST request to http://192.168.1.1/cgi/getParm to get the exponent (e) and modulus (n) that make up the router's public RSA key, in the form of some JS that gets eval()'d:</li>
</ul>
<div class="highlight"><pre><span></span><code><span class="kd">var</span><span class="w"> </span><span class="nx">ee</span><span class="o">=</span><span class="s2">"010001"</span><span class="p">;</span>
<span class="kd">var</span><span class="w"> </span><span class="nx">nn</span><span class="o">=</span><span class="s2">"CAD4D38AF8A98E13[snip]E5C66EE59B3D5753"</span><span class="p">;</span>
<span class="kd">var</span><span class="w"> </span><span class="nx">userSetting</span><span class="o">=</span><span class="mf">1</span><span class="p">;</span>
</code></pre></div>
<ul>
<li>The user enters the password and clicks the login button</li>
<li>The page encodes the password in base64 form, then encrypts it and the username "admin" using the RSA implementation in encrypt.js</li>
<li>The page makes a POST request to http://192.168.1.1/cgi/login?UserName=$USERRSA&Passwd=$PASSRSA&Action=1&LoginStatus=0</li>
<li>The POST's response constains a JSESSIONID cookie, which is required for future requests</li>
<li>The page redirects the browser to http://192.168.1.1 (with JSESSIONID set), which has some inline JS that sets a variable called <code>token</code>:</li>
</ul>
<div class="highlight"><pre><span></span><code><span class="p"><</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">"text/javascript"</span><span class="p">></span><span class="kd">var</span><span class="w"> </span><span class="nx">token</span><span class="o">=</span><span class="s2">"12f79fcd0620a9e01b1ccf6e627038"</span><span class="p">;</</span><span class="nt">script</span><span class="p">></span>
</code></pre></div>
<ul>
<li>The page makes various POST requests to the router with a TokenID header set to <code>token</code> from the previous step</li>
<li>When getting statistics, the page makes a POST request to http://192.168.1.1/cgi?1&1&1&1&1 with a string that looks as follows:</li>
</ul>
<div class="highlight"><pre><span></span><code>[WAN_COMMON_INTF_CFG#2,0,0,0,0,0#0,0,0,0,0,0]0,0
[WAN_LTE_INTF_CFG#2,0,0,0,0,0#0,0,0,0,0,0]1,8
dataLimit
enablePaymentDay
curStatistics
totalStatistics
enableDataLimit
limitation
curRxSpeed
curTxSpeed
[WAN_LTE_LINK_CFG#2,1,0,0,0,0#0,0,0,0,0,0]2,0
[LTE_PROF_STAT#2,1,0,0,0,0#0,0,0,0,0,0]3,0
[LTE_NET_STATUS#2,1,0,0,0,0#0,0,0,0,0,0]4,0
</code></pre></div>
<ul>
<li>This yields results like this:</li>
</ul>
<div class="highlight"><pre><span></span><code><span class="o">[</span><span class="n">2,0,0,0,0,0</span><span class="o">]</span><span class="mi">0</span>
<span class="n">enabledForInternet</span><span class="o">=</span><span class="mi">1</span>
<span class="n">WANAccessType</span><span class="o">=</span><span class="n">LTE</span>
<span class="n">layer1UpstreamMaxBitRate</span><span class="o">=</span><span class="mi">0</span>
<span class="n">layer1DownstreamMaxBitRate</span><span class="o">=</span><span class="mi">0</span>
<span class="w"> </span><span class="o">[</span><span class="n">snip</span><span class="o">]</span>
<span class="o">[</span><span class="n">2,0,0,0,0,0</span><span class="o">]</span><span class="mi">1</span>
<span class="n">dataLimit</span><span class="o">=</span><span class="mi">0</span>
<span class="n">enablePaymentDay</span><span class="o">=</span><span class="mi">0</span>
<span class="n">curStatistics</span><span class="o">=</span><span class="mi">0</span>
<span class="n">totalStatistics</span><span class="o">=</span><span class="mf">45374633.0000</span><span class="w"> </span><span class="o"><---</span><span class="w"> </span><span class="n">bingo</span><span class="err">!</span>
<span class="n">enableDataLimit</span><span class="o">=</span><span class="mi">0</span>
<span class="n">limitation</span><span class="o">=</span><span class="mi">0</span>
<span class="n">curRxSpeed</span><span class="o">=</span><span class="mi">2300</span>
<span class="n">curTxSpeed</span><span class="o">=</span><span class="mi">2183</span>
<span class="w"> </span><span class="o">[</span><span class="n">snip</span><span class="o">]</span>
</code></pre></div>
<p>All that's left to do at this point is to <code>grep</code> out whatever I'm interested in,
which gets sent to me via email 😎</p>
<p>There's not really any "hacking" in the Hollywood sense going on here,
just me being frustrated with TP-Link's nonsense.
It's my router, and I know the password.
The next section is about the case where someone doesn't know the password,
and how they could intercept it.</p>
<h2>Security analysis</h2>
<p>Since everything is sent in the clear it is quite obvious that this is nothing but feel-good "encryption".
The router sends both the public key and the encryption code to the client (a sysadmin most likely).
If an attacker can intercept and modify traffic they can do something like this:</p>
<ul>
<li>Detect when the modulus is being sent, modify it with their own modulus (the exponent can be kept the same)</li>
<li>Intercept any POST requests to http://192.168.1.1/cgi/login</li>
<li>Decrypt the UserName and Passwd query parameters using their private key</li>
<li>Re-encrypt UserName and Passwd using the router's public key, and send the request to the router</li>
</ul>
<p>The attacker now has the admin's password without them knowing.
If the admin is foolish then this password is probably used in other places.
In other words, TP-Link's solution here is not much better than basic HTTP auth.
It only provides (some) protection against sniffing.
It is likely that it doesn't actually protect against sniffing, for the following reasons:</p>
<ul>
<li>The modulus is only 1024 bits, which is uncomfortably close to being crackable in the near future</li>
<li>The public exponent is 4097, lower than the 65537 used in other RSA schemes</li>
<li>The modulus is regenerated every time the device boots, which probably means it is quite weak</li>
</ul>
<p>In the interest of audience participation, anyone with the computing resources to do so is encouraged to crack any of the following 1024-bit moduli:</p>
<div class="highlight"><pre><span></span><code>n1 = B32D3D91AF58FFD880ACEF2E651D39D2F4FE6D5E70459EDDAA1B0AAEB4156A91B1E259AF3E597FD4A9BD88F796F27FE9F737E42026C7895097CF54F6FC9BF8F65F9E020C2A11FB12FDAA812653D40F48F0006F5195A7CCEC8DA18DB0E1868E1DC0AAA9E82CEDC40B16F5DF21050747F7D4DB1B762B2B02B2D80AC5C5D0B5675B
n2 = CAD4D38AF8A98E13A785F424503C82E4DE1C61F9DFAB6D95391F2A0E40EB8017DF0381AEB4410C0CF5BD57CA84C3CA61003A401009623136C2873348FC27422287FD89C2221B8C251E74FD2FFB1EAAFF05EF7EDDA9D3E66C7CDFC2B42D5B1BCF1F1F427B303FEE1394EB1C59582A3A33E452C83A723E684BE5C66EE59B3D5753
n3 = AF64D40C6AD1855196A6B1EC166FE72B0ABF2D77A5F2B39868CC61684C2E9E7E73A0D0B1C6080FF7153089FACB9D6CA3BF7765DFCD2A9059047B3F93B96E0B18A8A998FD23B30B51C7BBA474FF4AF07A646AFB9A16D430F0BFF25886845DC09E924A8FFCD2299E7FC2A40D39812B013E8B46400D3AD2DEC5140EE624F3B70FF9
n4 = B94FA81B52B0331C30A14107561D4B298746C74AA9EE2C298D76C659E2532E0CFD51B8A73C59CD9D2A5722E092B59E7DF393E58533DA1643E2C91C78EA0BCA80FD1BC213FDE817D9CEB11CE5C1935680BC1D20D30D86919898CA684D9D37D1423637E347281BF9495BDF7B6F7E5ED9A9B311DF6654D50685714ED37C303DCAEB
n5 = DB7D39C7124B0EF5B1D03317FBC1612516B50DFD1C6AF4B78B79C19F8CCD701CD1C31A7BDD3D4E40A315B5579A423E7CFF67622CE841B6CB3F7F1163B5A9CB8F2B654FD319F8FA2F04201FC07012667644FAEAEA9CBF5A0FAAA2759FC01BE464C0817645B788444776A4A10611AEFE6A66A1ABCCAC442F2C7F1678A9D75CCD25
n6 = B3C1ABE0AF41651D775E4D69F59C1CC34FFCB9B746083862CF4DA20903C41EDC3CB38D17CB175E58AA54457C65DD4DE08C56B37DF2E54FD798E80D05CB135E048F6A106A8D645960E092EB59A3D4FDDF267CFF7E2467CC7E671223F1EFAF0DF2A70127F3C7837A32CCF9489E0B02549579D4BBC17CA789C8499F0C6EA8D03099
n7 = C115D236FF56C231706560E61F81625E1C4C34EA1469CD568E3B12D953BE774B83607A62842DA6376DC38112590F87BF15EC94A8796579E0C1A22E6536D57807BECC80F07DD533BD48536389680FA4739ACC4D9FF5EB82B611F86C1E738A8287726AF848F731D3DA91E13996857380AF0438D8C8DD7B44E13C323D0B13CCF52F
n8 = B82A85A1089C9F44525E11FCC0F4364A9B936C127DDB6C4E887C4D2651AC1D6C4CA03F768622D51444553DA800B43480A22CD5B6724D6872EDA6ABC5E6064027FD37A77974EB817EE00DE1837BAD96D52E982DC1546DD2C9CC5ED148541560D73AAAD594649318CCB6CCDECE117D557803B4EE3E747F067057ECCF836BD891B3
</code></pre></div>
<h2>Appendix</h2>
<h3>Bash script</h3>
<div class="highlight"><pre><span></span><code><span class="c1"># stop in case of errors</span>
<span class="nb">set</span><span class="w"> </span>-e
<span class="c1"># base64 encode password</span>
<span class="nv">PASSWORD</span><span class="o">=</span><span class="s2">"yourpassword"</span>
<span class="nv">PASS64</span><span class="o">=</span><span class="k">$(</span><span class="nb">echo</span><span class="w"> </span>-n<span class="w"> </span><span class="s2">"</span><span class="nv">$PASSWORD</span><span class="s2">"</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>base64<span class="k">)</span>
<span class="nb">echo</span><span class="w"> </span><span class="nv">PASS64</span><span class="o">=</span><span class="nv">$PASS64</span>
<span class="c1"># grab modulus (n) and exponent (e)</span>
<span class="c1"># this fails the first time after the modem has restarted</span>
<span class="c1"># just rerun this script if that happens</span>
curl<span class="w"> </span><span class="s1">'http://192.168.1.1/cgi/getParm'</span><span class="w"> </span>-H<span class="w"> </span><span class="s1">'Referer: http://192.168.1.1/'</span><span class="w"> </span>-X<span class="w"> </span>POST<span class="w"> </span><span class="p">|</span><span class="w"> </span>grep<span class="w"> </span>var<span class="w"> </span><span class="p">|</span><span class="w"> </span>tee<span class="w"> </span>/tmp/parm.js
<span class="c1"># append calls to rsa.encrypt(), print encrypted username and password</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"var jQuery = Object(); load('encrypt-stripped.js'); print('USERRSA='+jQuery.rsa.encrypt('admin', nn, ee)); print('PASSRSA='+jQuery.rsa.encrypt('</span><span class="nv">$PASS64</span><span class="s2">', nn, ee));"</span><span class="w"> </span>>><span class="w"> </span>/tmp/parm.js
rhino<span class="w"> </span>/tmp/parm.js<span class="w"> </span>><span class="w"> </span>/tmp/cred
<span class="nb">source</span><span class="w"> </span>/tmp/cred
<span class="nb">echo</span><span class="w"> </span><span class="nv">USERRSA</span><span class="o">=</span><span class="nv">$USERRSA</span>
<span class="nb">echo</span><span class="w"> </span><span class="nv">PASSRSA</span><span class="o">=</span><span class="nv">$PASSRSA</span>
curl<span class="w"> </span><span class="s2">"http://192.168.1.1/cgi/login?UserName=</span><span class="nv">$USERRSA</span><span class="s2">&Passwd=</span><span class="nv">$PASSRSA</span><span class="s2">&Action=1&LoginStatus=0"</span><span class="w"> </span>-H<span class="w"> </span><span class="s1">'User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:68.0) Gecko/20100101 Firefox/68.0'</span><span class="w"> </span>-H<span class="w"> </span><span class="s1">'Accept: */*'</span><span class="w"> </span>-H<span class="w"> </span><span class="s1">'Accept-Language: sv-SE,sv;q=0.8,en-US;q=0.5,en;q=0.3'</span><span class="w"> </span>--compressed<span class="w"> </span>-H<span class="w"> </span><span class="s1">'Referer: http://192.168.1.1/'</span><span class="w"> </span>-H<span class="w"> </span><span class="s1">'DNT: 1'</span><span class="w"> </span>-H<span class="w"> </span><span class="s1">'Connection: keep-alive'</span><span class="w"> </span>-H<span class="w"> </span><span class="s1">'Cookie: loginErrorShow=1'</span><span class="w"> </span>-H<span class="w"> </span><span class="s1">'Pragma: no-cache'</span><span class="w"> </span>-H<span class="w"> </span><span class="s1">'Cache-Control: no-cache'</span><span class="w"> </span>--data<span class="w"> </span><span class="s1">''</span><span class="w"> </span>-X<span class="w"> </span>POST<span class="w"> </span>--dump-header<span class="w"> </span>/tmp/router_headers.txt
<span class="nv">JSESSIONID</span><span class="o">=</span><span class="k">$(</span>grep<span class="w"> </span>JSESSIONID<span class="w"> </span>/tmp/router_headers.txt<span class="w"> </span><span class="p">|</span><span class="w"> </span>sed<span class="w"> </span>-e<span class="w"> </span><span class="s1">'s/.*JSESSIONID=//;s/;.*//'</span><span class="k">)</span>
<span class="nb">echo</span><span class="w"> </span><span class="nv">JSESSIONID</span><span class="o">=</span><span class="nv">$JSESSIONID</span>
<span class="nv">TOKENID</span><span class="o">=</span><span class="k">$(</span>curl<span class="w"> </span><span class="s1">'http://192.168.1.1/'</span><span class="w"> </span>-H<span class="w"> </span><span class="s1">'User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:68.0) Gecko/20100101 Firefox/68.0'</span><span class="w"> </span>-H<span class="w"> </span><span class="s1">'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'</span><span class="w"> </span>-H<span class="w"> </span><span class="s1">'Accept-Language: sv-SE,sv;q=0.8,en-US;q=0.5,en;q=0.3'</span><span class="w"> </span>--compressed<span class="w"> </span>-H<span class="w"> </span><span class="s1">'Referer: http://192.168.1.1/'</span><span class="w"> </span>-H<span class="w"> </span><span class="s1">'DNT: 1'</span><span class="w"> </span>-H<span class="w"> </span><span class="s1">'Connection: keep-alive'</span><span class="w"> </span>-H<span class="w"> </span><span class="s2">"Cookie: loginErrorShow=1; JSESSIONID=</span><span class="nv">$JSESSIONID</span><span class="s2">"</span><span class="w"> </span>-H<span class="w"> </span><span class="s1">'Upgrade-Insecure-Requests: 1'</span><span class="w"> </span>-H<span class="w"> </span><span class="s1">'Cache-Control: max-age=0'</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>grep<span class="w"> </span><span class="s2">"var token="</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>sed<span class="w"> </span>-e<span class="w"> </span><span class="s1">'s/.*var token="//;s/".*//'</span><span class="k">)</span>
<span class="nb">echo</span><span class="w"> </span><span class="nv">TOKENID</span><span class="o">=</span><span class="nv">$TOKENID</span>
curl<span class="w"> </span><span class="s1">'http://192.168.1.1/cgi?1&1&1&1&1'</span><span class="w"> </span>-H<span class="w"> </span><span class="s1">'User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:68.0) Gecko/20100101 Firefox/68.0'</span><span class="w"> </span>-H<span class="w"> </span><span class="s1">'Accept: */*'</span><span class="w"> </span>-H<span class="w"> </span><span class="s1">'Accept-Language: sv-SE,sv;q=0.8,en-US;q=0.5,en;q=0.3'</span><span class="w"> </span>--compressed<span class="w"> </span>-H<span class="w"> </span><span class="s1">'Referer: http://192.168.1.1/'</span><span class="w"> </span>-H<span class="w"> </span><span class="s2">"TokenID: </span><span class="nv">$TOKENID</span><span class="s2">"</span><span class="w"> </span>-H<span class="w"> </span><span class="s1">'Content-Type: text/plain'</span><span class="w"> </span>-H<span class="w"> </span><span class="s1">'DNT: 1'</span><span class="w"> </span>-H<span class="w"> </span><span class="s1">'Connection: keep-alive'</span><span class="w"> </span>-H<span class="w"> </span><span class="s2">"Cookie: loginErrorShow=1; JSESSIONID=</span><span class="nv">$JSESSIONID</span><span class="s2">"</span><span class="w"> </span>--data<span class="w"> </span><span class="s2">"</span><span class="k">$(</span>python<span class="w"> </span><span class="o"><<<</span><span class="w"> </span><span class="s1">'print("[WAN_COMMON_INTF_CFG#2,0,0,0,0,0#0,0,0,0,0,0]0,0\r\n[WAN_LTE_INTF_CFG#2,0,0,0,0,0#0,0,0,0,0,0]1,8\r\ndataLimit\r\nenablePaymentDay\r\ncurStatistics\r\ntotalStatistics\r\nenableDataLimit\r\nlimitation\r\ncurRxSpeed\r\ncurTxSpeed\r\n[WAN_LTE_LINK_CFG#2,1,0,0,0,0#0,0,0,0,0,0]2,0\r\n[LTE_PROF_STAT#2,1,0,0,0,0#0,0,0,0,0,0]3,0\r\n[LTE_NET_STATUS#2,1,0,0,0,0#0,0,0,0,0,0]4,0\r\n")'</span><span class="k">)</span><span class="s2">"</span><span class="w"> </span>-X<span class="w"> </span>POST<span class="w"> </span>><span class="w"> </span>/tmp/datapott.txt
<span class="nv">totalStatistics</span><span class="o">=</span><span class="k">$(</span>grep<span class="w"> </span>totalStatistics<span class="w"> </span>/tmp/datapott.txt<span class="w"> </span><span class="p">|</span><span class="w"> </span>sed<span class="w"> </span>-e<span class="w"> </span><span class="s1">'s/totalStatistics=//'</span><span class="k">)</span>
<span class="nv">SUBJECT</span><span class="o">=</span><span class="k">$(</span>python3<span class="w"> </span><span class="o"><<<</span><span class="w"> </span><span class="s2">"print('%.1f MiB av 15000 (%.1f%%)' % (</span><span class="nv">$totalStatistics</span><span class="s2">/1048576, </span><span class="nv">$totalStatistics</span><span class="s2">*100/1048576/15000));"</span><span class="k">)</span>
<span class="nb">echo</span><span class="w"> </span><span class="nv">SUBJECT</span><span class="o">=</span><span class="s2">"</span><span class="nv">$SUBJECT</span><span class="s2">"</span>
egrep<span class="w"> </span><span class="s1">'Speed|totalStatistics|ipv4=|ipv6=|simCardImsi|smsScAddress|gatewayV4|gatewayV6'</span><span class="w"> </span>/tmp/datapott.txt<span class="w"> </span><span class="p">|</span><span class="w"> </span>tee<span class="w"> </span>/tmp/mail.txt
./check_ocxo.sh<span class="w"> </span>>><span class="w"> </span>/tmp/mail.txt
uptime<span class="w"> </span>>><span class="w"> </span>/tmp/mail.txt
ssh<span class="w"> </span>your_machine<span class="w"> </span>mail<span class="w"> </span>-s<span class="w"> </span><span class="s2">"\"</span><span class="nv">$SUBJECT</span><span class="s2">\""</span><span class="w"> </span>your_username<span class="w"> </span><<span class="w"> </span>/tmp/mail.txt
</code></pre></div>
<h3>encrypt-stripped.js</h3>
<div class="highlight"><pre><span></span><code><span class="o">!</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">$</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="nx">$</span><span class="p">.</span><span class="nx">rsa</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">$</span><span class="p">.</span><span class="nx">rsa</span><span class="w"> </span><span class="o">||</span>
<span class="w"> </span><span class="p">{},</span><span class="w"> </span><span class="nx">$</span><span class="p">.</span><span class="nx">rsa</span><span class="p">.</span><span class="nx">encrypt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">val</span><span class="p">,</span><span class="w"> </span><span class="nx">nn</span><span class="p">,</span><span class="w"> </span><span class="nx">ee</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="w"> </span><span class="nx">b</span><span class="p">,</span><span class="w"> </span><span class="nx">c</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kc">null</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="s2">"number"</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="ow">typeof</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">fromNumber</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="w"> </span><span class="nx">b</span><span class="p">,</span><span class="w"> </span><span class="nx">c</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="kc">null</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">b</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="s2">"string"</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="ow">typeof</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">fromString</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="w"> </span><span class="mf">256</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">fromString</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="w"> </span><span class="nx">b</span><span class="p">))</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">nbi</span><span class="p">()</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">(</span><span class="kc">null</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">int2char</span><span class="p">(</span><span class="nx">n</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">BI_RM</span><span class="p">.</span><span class="nx">charAt</span><span class="p">(</span><span class="nx">n</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">intAt</span><span class="p">(</span><span class="nx">s</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">BI_RC</span><span class="p">[</span><span class="nx">s</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">i</span><span class="p">)];</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="kc">null</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="o">-</span><span class="mf">1</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="nx">c</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">nbv</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">nbi</span><span class="p">();</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">fromInt</span><span class="p">(</span><span class="nx">i</span><span class="p">),</span><span class="w"> </span><span class="nx">r</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">nbits</span><span class="p">(</span><span class="nx">x</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">t</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">1</span><span class="p">;</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="p">(</span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">16</span><span class="p">)</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">t</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mf">16</span><span class="p">),</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="p">(</span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="mf">8</span><span class="p">)</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">t</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mf">8</span><span class="p">),</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="p">(</span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="mf">4</span><span class="p">)</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">t</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mf">4</span><span class="p">),</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="p">(</span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="mf">2</span><span class="p">)</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">t</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mf">2</span><span class="p">),</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="p">(</span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="mf">1</span><span class="p">)</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">t</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mf">1</span><span class="p">),</span><span class="w"> </span><span class="nx">r</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">Classic</span><span class="p">(</span><span class="nx">m</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">m</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">m</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">Montgomery</span><span class="p">(</span><span class="nx">m</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">m</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">m</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">mp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">m</span><span class="p">.</span><span class="nx">invDigit</span><span class="p">(),</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">mpl</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">32767</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">mp</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">mph</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">mp</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="mf">15</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">um</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="mf">1</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="nx">m</span><span class="p">.</span><span class="nx">DB</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">15</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">mt2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">m</span><span class="p">.</span><span class="nx">t</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">Arcfour</span><span class="p">()</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">S</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">prng_newstate</span><span class="p">()</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Arcfour</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">rng_seed_int</span><span class="p">(</span><span class="nx">x</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">rng_pool</span><span class="p">[</span><span class="nx">rng_pptr</span><span class="o">++</span><span class="p">]</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="mf">255</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="nx">x</span><span class="p">,</span><span class="w"> </span><span class="nx">rng_pool</span><span class="p">[</span><span class="nx">rng_pptr</span><span class="o">++</span><span class="p">]</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="mf">8</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">255</span><span class="p">,</span><span class="w"> </span><span class="nx">rng_pool</span><span class="p">[</span><span class="nx">rng_pptr</span><span class="o">++</span><span class="p">]</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">255</span><span class="p">,</span><span class="w"> </span><span class="nx">rng_pool</span><span class="p">[</span><span class="nx">rng_pptr</span><span class="o">++</span><span class="p">]</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="mf">24</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">255</span><span class="p">,</span><span class="w"> </span><span class="nx">rng_pptr</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="nx">rng_psize</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">rng_pptr</span><span class="w"> </span><span class="o">-=</span><span class="w"> </span><span class="nx">rng_psize</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">rng_seed_time</span><span class="p">()</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">rng_seed_int</span><span class="p">((</span><span class="ow">new</span><span class="w"> </span><span class="nb">Date</span><span class="p">).</span><span class="nx">getTime</span><span class="p">())</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">rng_get_byte</span><span class="p">()</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="kc">null</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">rng_state</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="nx">rng_seed_time</span><span class="p">(),</span><span class="w"> </span><span class="p">(</span><span class="nx">rng_state</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">prng_newstate</span><span class="p">()).</span><span class="nx">init</span><span class="p">(</span><span class="nx">rng_pool</span><span class="p">),</span><span class="w"> </span><span class="nx">rng_pptr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">rng_pptr</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">rng_pool</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="nx">rng_pptr</span><span class="p">)</span><span class="w"> </span><span class="nx">rng_pool</span><span class="p">[</span><span class="nx">rng_pptr</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span>
<span class="w"> </span><span class="nx">rng_pptr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">rng_state</span><span class="p">.</span><span class="nx">next</span><span class="p">()</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">SecureRandom</span><span class="p">()</span>
<span class="w"> </span><span class="p">{}</span>
<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">parseBigInt</span><span class="p">(</span><span class="nx">str</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">(</span><span class="nx">str</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">pkcs1pad2</span><span class="p">(</span><span class="nx">s</span><span class="p">,</span><span class="w"> </span><span class="nx">n</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">n</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">s</span><span class="p">.</span><span class="nx">length</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">11</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="kc">null</span><span class="p">;</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">var</span><span class="w"> </span><span class="nx">ba</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">s</span><span class="p">.</span><span class="nx">length</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">0</span><span class="p">;)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">s</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">i</span><span class="o">--</span><span class="p">);</span>
<span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mf">128</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="nx">ba</span><span class="p">[</span><span class="o">--</span><span class="nx">n</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">127</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mf">2048</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="p">(</span><span class="nx">ba</span><span class="p">[</span><span class="o">--</span><span class="nx">n</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">63</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="mf">128</span><span class="p">,</span><span class="w"> </span><span class="nx">ba</span><span class="p">[</span><span class="o">--</span><span class="nx">n</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="mf">6</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="mf">192</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">ba</span><span class="p">[</span><span class="o">--</span><span class="nx">n</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">63</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="mf">128</span><span class="p">,</span><span class="w"> </span><span class="nx">ba</span><span class="p">[</span><span class="o">--</span><span class="nx">n</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="mf">6</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">63</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="mf">128</span><span class="p">,</span><span class="w"> </span><span class="nx">ba</span><span class="p">[</span><span class="o">--</span><span class="nx">n</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="mf">12</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="mf">224</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="nx">ba</span><span class="p">[</span><span class="o">--</span><span class="nx">n</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">var</span><span class="w"> </span><span class="nx">rng</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">SecureRandom</span><span class="p">,</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">;</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">2</span><span class="p">;)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">x</span><span class="p">[</span><span class="mf">0</span><span class="p">];)</span><span class="w"> </span><span class="nx">rng</span><span class="p">.</span><span class="nx">nextBytes</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="w"> </span><span class="nx">ba</span><span class="p">[</span><span class="o">--</span><span class="nx">n</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">x</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">ba</span><span class="p">[</span><span class="o">--</span><span class="nx">n</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="nx">ba</span><span class="p">[</span><span class="o">--</span><span class="nx">n</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">(</span><span class="nx">ba</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">RSAKey</span><span class="p">()</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">e</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">d</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">p</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">q</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">dmp1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">dmq1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">coeff</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">null</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">dbits</span><span class="p">;</span>
<span class="w"> </span><span class="cm">/*"Microsoft Internet Explorer" == navigator.appName ? (BigInteger.prototype.am = function (i, x, w, j, c, n)</span>
<span class="cm"> {</span>
<span class="cm"> for (var xl = 32767 & x, xh = x >> 15; --n >= 0;)</span>
<span class="cm"> {</span>
<span class="cm"> var l = 32767 & this[i],</span>
<span class="cm"> h = this[i++] >> 15,</span>
<span class="cm"> m = xh * l + h * xl;</span>
<span class="cm"> c = ((l = xl * l + ((32767 & m) << 15) + w[j] + (1073741823 & c)) >>> 30) + (m >>> 15) + xh * h + (c >>> 30), w[j++] = 1073741823 & l</span>
<span class="cm"> }</span>
<span class="cm"> return c</span>
<span class="cm"> }, dbits = 30) : "Netscape" != navigator.appName ? (BigInteger.prototype.am = function (i, x, w, j, c, n)</span>
<span class="cm"> {</span>
<span class="cm"> for (; --n >= 0;)</span>
<span class="cm"> {</span>
<span class="cm"> var v = x * this[i++] + w[j] + c;</span>
<span class="cm"> c = Math.floor(v / 67108864), w[j++] = 67108863 & v</span>
<span class="cm"> }</span>
<span class="cm"> return c</span>
<span class="cm"> }, dbits = 26) :*/</span><span class="w"> </span><span class="p">(</span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">am</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">i</span><span class="p">,</span><span class="w"> </span><span class="nx">x</span><span class="p">,</span><span class="w"> </span><span class="nx">w</span><span class="p">,</span><span class="w"> </span><span class="nx">j</span><span class="p">,</span><span class="w"> </span><span class="nx">c</span><span class="p">,</span><span class="w"> </span><span class="nx">n</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">var</span><span class="w"> </span><span class="nx">xl</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">16383</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="nx">x</span><span class="p">,</span><span class="w"> </span><span class="nx">xh</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="mf">14</span><span class="p">;</span>
<span class="w"> </span><span class="o">--</span><span class="nx">n</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="mf">0</span><span class="p">;)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">l</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">16383</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="k">this</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span>
<span class="w"> </span><span class="nx">h</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">[</span><span class="nx">i</span><span class="o">++</span><span class="p">]</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="mf">14</span><span class="p">,</span>
<span class="w"> </span><span class="nx">m</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">xh</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">l</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">h</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">xl</span><span class="p">;</span>
<span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">((</span><span class="nx">l</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">xl</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">l</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">((</span><span class="mf">16383</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="nx">m</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">14</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">w</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">c</span><span class="p">)</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="mf">28</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="nx">m</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="mf">14</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">xh</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">h</span><span class="p">,</span><span class="w"> </span><span class="nx">w</span><span class="p">[</span><span class="nx">j</span><span class="o">++</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">268435455</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="nx">l</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">c</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">dbits</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">28</span><span class="p">),</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">DB</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">dbits</span><span class="p">,</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">DM</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="mf">1</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="nx">dbits</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">DV</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="nx">dbits</span><span class="p">;</span>
<span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">FV</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="mf">52</span><span class="p">),</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">F1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">52</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">dbits</span><span class="p">,</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">F2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">dbits</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">52</span><span class="p">;</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">rr</span><span class="p">,</span><span class="w"> </span><span class="nx">vv</span><span class="p">,</span><span class="w"> </span><span class="nx">BI_RM</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"0123456789abcdefghijklmnopqrstuvwxyz"</span><span class="p">,</span>
<span class="w"> </span><span class="nx">BI_RC</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">;</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="nx">rr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"0"</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="mf">0</span><span class="p">),</span><span class="w"> </span><span class="nx">vv</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">vv</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="mf">9</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="nx">vv</span><span class="p">)</span><span class="w"> </span><span class="nx">BI_RC</span><span class="p">[</span><span class="nx">rr</span><span class="o">++</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">vv</span><span class="p">;</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="nx">rr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"a"</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="mf">0</span><span class="p">),</span><span class="w"> </span><span class="nx">vv</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">10</span><span class="p">;</span><span class="w"> </span><span class="nx">vv</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mf">36</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="nx">vv</span><span class="p">)</span><span class="w"> </span><span class="nx">BI_RC</span><span class="p">[</span><span class="nx">rr</span><span class="o">++</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">vv</span><span class="p">;</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="nx">rr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"A"</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="mf">0</span><span class="p">),</span><span class="w"> </span><span class="nx">vv</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">10</span><span class="p">;</span><span class="w"> </span><span class="nx">vv</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mf">36</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="nx">vv</span><span class="p">)</span><span class="w"> </span><span class="nx">BI_RC</span><span class="p">[</span><span class="nx">rr</span><span class="o">++</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">vv</span><span class="p">;</span>
<span class="w"> </span><span class="nx">Classic</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">convert</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">s</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">compareTo</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">m</span><span class="p">)</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">mod</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">m</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="nx">x</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">Classic</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">revert</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">x</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">Classic</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">reduce</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">divRemTo</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">m</span><span class="p">,</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w"> </span><span class="nx">x</span><span class="p">)</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">Classic</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">mulTo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="p">,</span><span class="w"> </span><span class="nx">y</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">multiplyTo</span><span class="p">(</span><span class="nx">y</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">),</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">reduce</span><span class="p">(</span><span class="nx">r</span><span class="p">)</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">Classic</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">sqrTo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">squareTo</span><span class="p">(</span><span class="nx">r</span><span class="p">),</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">reduce</span><span class="p">(</span><span class="nx">r</span><span class="p">)</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">Montgomery</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">convert</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">nbi</span><span class="p">();</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">abs</span><span class="p">().</span><span class="nx">dlShiftTo</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">m</span><span class="p">.</span><span class="nx">t</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">),</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">divRemTo</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">m</span><span class="p">,</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">),</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">s</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">compareTo</span><span class="p">(</span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">ZERO</span><span class="p">)</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">m</span><span class="p">.</span><span class="nx">subTo</span><span class="p">(</span><span class="nx">r</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">),</span><span class="w"> </span><span class="nx">r</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">Montgomery</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">revert</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">nbi</span><span class="p">();</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">copyTo</span><span class="p">(</span><span class="nx">r</span><span class="p">),</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">reduce</span><span class="p">(</span><span class="nx">r</span><span class="p">),</span><span class="w"> </span><span class="nx">r</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">Montgomery</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">reduce</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(;</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">mt2</span><span class="p">;)</span><span class="w"> </span><span class="nx">x</span><span class="p">[</span><span class="nx">x</span><span class="p">.</span><span class="nx">t</span><span class="o">++</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">var</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">m</span><span class="p">.</span><span class="nx">t</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="nx">i</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">32767</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="nx">x</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span>
<span class="w"> </span><span class="nx">u0</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">j</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">mpl</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">((</span><span class="nx">j</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">mph</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="mf">15</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">mpl</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">um</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">15</span><span class="p">)</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">DM</span><span class="p">;</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="p">[</span><span class="nx">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">m</span><span class="p">.</span><span class="nx">t</span><span class="p">]</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">m</span><span class="p">.</span><span class="nx">am</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">u0</span><span class="p">,</span><span class="w"> </span><span class="nx">x</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">m</span><span class="p">.</span><span class="nx">t</span><span class="p">);</span><span class="w"> </span><span class="nx">x</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">DV</span><span class="p">;)</span><span class="w"> </span><span class="nx">x</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span><span class="w"> </span><span class="o">-=</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">DV</span><span class="p">,</span><span class="w"> </span><span class="nx">x</span><span class="p">[</span><span class="o">++</span><span class="nx">j</span><span class="p">]</span><span class="o">++</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">clamp</span><span class="p">(),</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">drShiftTo</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">m</span><span class="p">.</span><span class="nx">t</span><span class="p">,</span><span class="w"> </span><span class="nx">x</span><span class="p">),</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">compareTo</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">m</span><span class="p">)</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">subTo</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">m</span><span class="p">,</span><span class="w"> </span><span class="nx">x</span><span class="p">)</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">Montgomery</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">mulTo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="p">,</span><span class="w"> </span><span class="nx">y</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">multiplyTo</span><span class="p">(</span><span class="nx">y</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">),</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">reduce</span><span class="p">(</span><span class="nx">r</span><span class="p">)</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">Montgomery</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">sqrTo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">squareTo</span><span class="p">(</span><span class="nx">r</span><span class="p">),</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">reduce</span><span class="p">(</span><span class="nx">r</span><span class="p">)</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">copyTo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">r</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">var</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="o">--</span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
<span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">s</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">s</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">fromInt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">s</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="o">-</span><span class="mf">1</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="k">this</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="o">-</span><span class="mf">1</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="k">this</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DV</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">fromString</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">s</span><span class="p">,</span><span class="w"> </span><span class="nx">b</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">k</span><span class="p">;</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="mf">16</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">b</span><span class="p">)</span><span class="w"> </span><span class="nx">k</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">4</span><span class="p">;</span>
<span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="mf">8</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">b</span><span class="p">)</span><span class="w"> </span><span class="nx">k</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">3</span><span class="p">;</span>
<span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="mf">256</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">b</span><span class="p">)</span><span class="w"> </span><span class="nx">k</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">8</span><span class="p">;</span>
<span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="mf">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">b</span><span class="p">)</span><span class="w"> </span><span class="nx">k</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">1</span><span class="p">;</span>
<span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="mf">32</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">b</span><span class="p">)</span><span class="w"> </span><span class="nx">k</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">5</span><span class="p">;</span>
<span class="w"> </span><span class="k">else</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="mf">4</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nx">b</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="ow">void</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">fromRadix</span><span class="p">(</span><span class="nx">s</span><span class="p">,</span><span class="w"> </span><span class="nx">b</span><span class="p">);</span>
<span class="w"> </span><span class="nx">k</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">2</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">s</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">var</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">s</span><span class="p">.</span><span class="nx">length</span><span class="p">,</span><span class="w"> </span><span class="nx">mi</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">!</span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="nx">sh</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span>
<span class="w"> </span><span class="o">--</span><span class="nx">i</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="mf">0</span><span class="p">;)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">8</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">k</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="mf">255</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="nx">s</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="nx">intAt</span><span class="p">(</span><span class="nx">s</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">);</span>
<span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="s2">"-"</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">s</span><span class="p">.</span><span class="nx">charAt</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">mi</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">!</span><span class="mf">0</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">mi</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">!</span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">sh</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="k">this</span><span class="p">[</span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="o">++</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="nx">sh</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">k</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DB</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="p">(</span><span class="k">this</span><span class="p">[</span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">]</span><span class="w"> </span><span class="o">|=</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="p">(</span><span class="mf">1</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DB</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">sh</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="nx">sh</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">[</span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="o">++</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DB</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">sh</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="k">this</span><span class="p">[</span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">]</span><span class="w"> </span><span class="o">|=</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="nx">sh</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="nx">sh</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="nx">k</span><span class="p">)</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DB</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">sh</span><span class="w"> </span><span class="o">-=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DB</span><span class="p">))</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="mf">8</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">k</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="p">(</span><span class="mf">128</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="nx">s</span><span class="p">[</span><span class="mf">0</span><span class="p">])</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">s</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">-</span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="nx">sh</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="k">this</span><span class="p">[</span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">]</span><span class="w"> </span><span class="o">|=</span><span class="w"> </span><span class="p">(</span><span class="mf">1</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DB</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">sh</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="nx">sh</span><span class="p">)),</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">clamp</span><span class="p">(),</span><span class="w"> </span><span class="nx">mi</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">ZERO</span><span class="p">.</span><span class="nx">subTo</span><span class="p">(</span><span class="k">this</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">)</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">clamp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">()</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">var</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">s</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DM</span><span class="p">;</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="k">this</span><span class="p">[</span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">]</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">c</span><span class="p">;)</span><span class="w"> </span><span class="o">--</span><span class="k">this</span><span class="p">.</span><span class="nx">t</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">dlShiftTo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">n</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">i</span><span class="p">;</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="o">--</span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="nx">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">n</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="o">--</span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span>
<span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">n</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">s</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">s</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">drShiftTo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">n</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">var</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">n</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="nx">i</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">n</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
<span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">max</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">n</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">),</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">s</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">s</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">lShiftTo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">n</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">i</span><span class="p">,</span><span class="w"> </span><span class="nx">bs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DB</span><span class="p">,</span>
<span class="w"> </span><span class="nx">cbs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DB</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">bs</span><span class="p">,</span>
<span class="w"> </span><span class="nx">bm</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="mf">1</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="nx">cbs</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span>
<span class="w"> </span><span class="nx">ds</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">floor</span><span class="p">(</span><span class="nx">n</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DB</span><span class="p">),</span>
<span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">s</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="nx">bs</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DM</span><span class="p">;</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="o">--</span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="nx">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">ds</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="nx">cbs</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">c</span><span class="p">,</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="k">this</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="nx">bm</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="nx">bs</span><span class="p">;</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">ds</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="o">--</span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span>
<span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="nx">ds</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">c</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">ds</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">s</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">s</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">clamp</span><span class="p">()</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">rShiftTo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">n</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">s</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">s</span><span class="p">;</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">ds</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">floor</span><span class="p">(</span><span class="nx">n</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DB</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">ds</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="p">)</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span>
<span class="w"> </span><span class="k">else</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">bs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DB</span><span class="p">,</span>
<span class="w"> </span><span class="nx">cbs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DB</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">bs</span><span class="p">,</span>
<span class="w"> </span><span class="nx">bm</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="mf">1</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="nx">bs</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">;</span>
<span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">[</span><span class="nx">ds</span><span class="p">]</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="nx">bs</span><span class="p">;</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">var</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">ds</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">1</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="p">;</span>
<span class="w"> </span><span class="o">++</span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="nx">i</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">ds</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">]</span><span class="w"> </span><span class="o">|=</span><span class="w"> </span><span class="p">(</span><span class="k">this</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="nx">bm</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="nx">cbs</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="nx">i</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">ds</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="nx">bs</span><span class="p">;</span>
<span class="w"> </span><span class="nx">bs</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">r</span><span class="p">[</span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">ds</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">]</span><span class="w"> </span><span class="o">|=</span><span class="w"> </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">s</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="nx">bm</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="nx">cbs</span><span class="p">),</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">ds</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">clamp</span><span class="p">()</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">subTo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">var</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">m</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">min</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">t</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="p">);</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">m</span><span class="p">;)</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="k">this</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">a</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="nx">i</span><span class="o">++</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DM</span><span class="p">,</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">>>=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DB</span><span class="p">;</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="nx">c</span><span class="w"> </span><span class="o">-=</span><span class="w"> </span><span class="nx">a</span><span class="p">.</span><span class="nx">s</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="p">;)</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="k">this</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="nx">i</span><span class="o">++</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DM</span><span class="p">,</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">>>=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DB</span><span class="p">;</span>
<span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">s</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">else</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="nx">c</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">s</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">a</span><span class="p">.</span><span class="nx">t</span><span class="p">;)</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">-=</span><span class="w"> </span><span class="nx">a</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="nx">i</span><span class="o">++</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DM</span><span class="p">,</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">>>=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DB</span><span class="p">;</span>
<span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">-=</span><span class="w"> </span><span class="nx">a</span><span class="p">.</span><span class="nx">s</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">s</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="o">-</span><span class="mf">1</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="o">-</span><span class="mf">1</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="nx">i</span><span class="o">++</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DV</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">r</span><span class="p">[</span><span class="nx">i</span><span class="o">++</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">c</span><span class="p">),</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">i</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">clamp</span><span class="p">()</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">multiplyTo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">abs</span><span class="p">(),</span>
<span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">a</span><span class="p">.</span><span class="nx">abs</span><span class="p">(),</span>
<span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">t</span><span class="p">;</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="nx">r</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">y</span><span class="p">.</span><span class="nx">t</span><span class="p">;</span><span class="w"> </span><span class="o">--</span><span class="nx">i</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="mf">0</span><span class="p">;)</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">y</span><span class="p">.</span><span class="nx">t</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="nx">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">t</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">am</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">y</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span><span class="w"> </span><span class="nx">r</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">t</span><span class="p">);</span>
<span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">s</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">clamp</span><span class="p">(),</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">s</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nx">a</span><span class="p">.</span><span class="nx">s</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">ZERO</span><span class="p">.</span><span class="nx">subTo</span><span class="p">(</span><span class="nx">r</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">)</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">squareTo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">r</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">var</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">abs</span><span class="p">(),</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">t</span><span class="p">;</span><span class="w"> </span><span class="o">--</span><span class="nx">i</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="mf">0</span><span class="p">;)</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="nx">i</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">am</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span><span class="w"> </span><span class="nx">x</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span><span class="w"> </span><span class="nx">r</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">i</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">);</span>
<span class="w"> </span><span class="p">(</span><span class="nx">r</span><span class="p">[</span><span class="nx">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">t</span><span class="p">]</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">am</span><span class="p">(</span><span class="nx">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">x</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span><span class="w"> </span><span class="nx">r</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="nx">c</span><span class="p">,</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">))</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">DV</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">r</span><span class="p">[</span><span class="nx">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">t</span><span class="p">]</span><span class="w"> </span><span class="o">-=</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">DV</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="nx">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">1</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">r</span><span class="p">[</span><span class="nx">r</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">]</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">am</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span><span class="w"> </span><span class="nx">x</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span><span class="w"> </span><span class="nx">r</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">i</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">)),</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">s</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">clamp</span><span class="p">()</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">divRemTo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">m</span><span class="p">,</span><span class="w"> </span><span class="nx">q</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">pm</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">m</span><span class="p">.</span><span class="nx">abs</span><span class="p">();</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="p">(</span><span class="nx">pm</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="mf">0</span><span class="p">))</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">pt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">abs</span><span class="p">();</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">pt</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">pm</span><span class="p">.</span><span class="nx">t</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="kc">null</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nx">q</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="nx">q</span><span class="p">.</span><span class="nx">fromInt</span><span class="p">(</span><span class="mf">0</span><span class="p">),</span><span class="w"> </span><span class="ow">void</span><span class="p">(</span><span class="kc">null</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">copyTo</span><span class="p">(</span><span class="nx">r</span><span class="p">));</span>
<span class="w"> </span><span class="kc">null</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">nbi</span><span class="p">());</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">nbi</span><span class="p">(),</span>
<span class="w"> </span><span class="nx">ts</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">s</span><span class="p">,</span>
<span class="w"> </span><span class="nx">ms</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">m</span><span class="p">.</span><span class="nx">s</span><span class="p">,</span>
<span class="w"> </span><span class="nx">nsh</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DB</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">nbits</span><span class="p">(</span><span class="nx">pm</span><span class="p">[</span><span class="nx">pm</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">]);</span>
<span class="w"> </span><span class="nx">nsh</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="p">(</span><span class="nx">pm</span><span class="p">.</span><span class="nx">lShiftTo</span><span class="p">(</span><span class="nx">nsh</span><span class="p">,</span><span class="w"> </span><span class="nx">y</span><span class="p">),</span><span class="w"> </span><span class="nx">pt</span><span class="p">.</span><span class="nx">lShiftTo</span><span class="p">(</span><span class="nx">nsh</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">))</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">pm</span><span class="p">.</span><span class="nx">copyTo</span><span class="p">(</span><span class="nx">y</span><span class="p">),</span><span class="w"> </span><span class="nx">pt</span><span class="p">.</span><span class="nx">copyTo</span><span class="p">(</span><span class="nx">r</span><span class="p">));</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">ys</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">y</span><span class="p">.</span><span class="nx">t</span><span class="p">,</span>
<span class="w"> </span><span class="nx">y0</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">y</span><span class="p">[</span><span class="nx">ys</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">];</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="mf">0</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nx">y0</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">yt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">y0</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">(</span><span class="mf">1</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">F1</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="nx">ys</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="nx">y</span><span class="p">[</span><span class="nx">ys</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">2</span><span class="p">]</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">F2</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="mf">0</span><span class="p">),</span>
<span class="w"> </span><span class="nx">d1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">FV</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nx">yt</span><span class="p">,</span>
<span class="w"> </span><span class="nx">d2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="mf">1</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">F1</span><span class="p">)</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nx">yt</span><span class="p">,</span>
<span class="w"> </span><span class="nx">e</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">F2</span><span class="p">,</span>
<span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">t</span><span class="p">,</span>
<span class="w"> </span><span class="nx">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">ys</span><span class="p">,</span>
<span class="w"> </span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">null</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">q</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="nx">nbi</span><span class="p">()</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="nx">q</span><span class="p">;</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="nx">y</span><span class="p">.</span><span class="nx">dlShiftTo</span><span class="p">(</span><span class="nx">j</span><span class="p">,</span><span class="w"> </span><span class="nx">t</span><span class="p">),</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">compareTo</span><span class="p">(</span><span class="nx">t</span><span class="p">)</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">r</span><span class="p">[</span><span class="nx">r</span><span class="p">.</span><span class="nx">t</span><span class="o">++</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">subTo</span><span class="p">(</span><span class="nx">t</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">)),</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">ONE</span><span class="p">.</span><span class="nx">dlShiftTo</span><span class="p">(</span><span class="nx">ys</span><span class="p">,</span><span class="w"> </span><span class="nx">t</span><span class="p">),</span><span class="w"> </span><span class="nx">t</span><span class="p">.</span><span class="nx">subTo</span><span class="p">(</span><span class="nx">y</span><span class="p">,</span><span class="w"> </span><span class="nx">y</span><span class="p">);</span><span class="w"> </span><span class="nx">y</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">ys</span><span class="p">;)</span><span class="w"> </span><span class="nx">y</span><span class="p">[</span><span class="nx">y</span><span class="p">.</span><span class="nx">t</span><span class="o">++</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(;</span><span class="w"> </span><span class="o">--</span><span class="nx">j</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="mf">0</span><span class="p">;)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">qd</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="o">--</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">y0</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DM</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">floor</span><span class="p">(</span><span class="nx">r</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">d1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="nx">r</span><span class="p">[</span><span class="nx">i</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">e</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">d2</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">((</span><span class="nx">r</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="nx">y</span><span class="p">.</span><span class="nx">am</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">qd</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">,</span><span class="w"> </span><span class="nx">j</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">ys</span><span class="p">))</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">qd</span><span class="p">)</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="nx">y</span><span class="p">.</span><span class="nx">dlShiftTo</span><span class="p">(</span><span class="nx">j</span><span class="p">,</span><span class="w"> </span><span class="nx">t</span><span class="p">),</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">subTo</span><span class="p">(</span><span class="nx">t</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">);</span><span class="w"> </span><span class="nx">r</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="o">--</span><span class="nx">qd</span><span class="p">;)</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">subTo</span><span class="p">(</span><span class="nx">t</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kc">null</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nx">q</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">r</span><span class="p">.</span><span class="nx">drShiftTo</span><span class="p">(</span><span class="nx">ys</span><span class="p">,</span><span class="w"> </span><span class="nx">q</span><span class="p">),</span><span class="w"> </span><span class="nx">ts</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nx">ms</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">ZERO</span><span class="p">.</span><span class="nx">subTo</span><span class="p">(</span><span class="nx">q</span><span class="p">,</span><span class="w"> </span><span class="nx">q</span><span class="p">)),</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">ys</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">clamp</span><span class="p">(),</span><span class="w"> </span><span class="nx">nsh</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">rShiftTo</span><span class="p">(</span><span class="nx">nsh</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">),</span><span class="w"> </span><span class="nx">ts</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">ZERO</span><span class="p">.</span><span class="nx">subTo</span><span class="p">(</span><span class="nx">r</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">invDigit</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">()</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mf">1</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">[</span><span class="mf">0</span><span class="p">];</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="mf">0</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="p">(</span><span class="mf">1</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="nx">x</span><span class="p">))</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">3</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="nx">x</span><span class="p">;</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">(</span><span class="mf">2</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="p">(</span><span class="mf">15</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="nx">x</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">y</span><span class="p">)</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">15</span><span class="p">,</span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">(</span><span class="mf">2</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="p">(</span><span class="mf">255</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="nx">x</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">y</span><span class="p">)</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">255</span><span class="p">,</span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">(</span><span class="mf">2</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="p">((</span><span class="mf">65535</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="nx">x</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">65535</span><span class="p">))</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">65535</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="nx">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">(</span><span class="mf">2</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DV</span><span class="p">)</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DV</span><span class="p">)</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DV</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="o">-</span><span class="nx">y</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">isEven</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">()</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="k">this</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">s</span><span class="p">)</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">exp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">e</span><span class="p">,</span><span class="w"> </span><span class="nx">z</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">e</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">4294967295</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="nx">e</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mf">1</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">ONE</span><span class="p">;</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">nbi</span><span class="p">(),</span>
<span class="w"> </span><span class="nx">r2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">nbi</span><span class="p">(),</span>
<span class="w"> </span><span class="nx">g</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">z</span><span class="p">.</span><span class="nx">convert</span><span class="p">(</span><span class="k">this</span><span class="p">),</span>
<span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">nbits</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">;</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="nx">g</span><span class="p">.</span><span class="nx">copyTo</span><span class="p">(</span><span class="nx">r</span><span class="p">);</span><span class="w"> </span><span class="o">--</span><span class="nx">i</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="mf">0</span><span class="p">;)</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">z</span><span class="p">.</span><span class="nx">sqrTo</span><span class="p">(</span><span class="nx">r</span><span class="p">,</span><span class="w"> </span><span class="nx">r2</span><span class="p">),</span><span class="w"> </span><span class="p">(</span><span class="nx">e</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">0</span><span class="p">)</span><span class="w"> </span><span class="nx">z</span><span class="p">.</span><span class="nx">mulTo</span><span class="p">(</span><span class="nx">r2</span><span class="p">,</span><span class="w"> </span><span class="nx">g</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">);</span>
<span class="w"> </span><span class="k">else</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">r</span><span class="p">;</span>
<span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">r2</span><span class="p">,</span><span class="w"> </span><span class="nx">r2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">t</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">z</span><span class="p">.</span><span class="nx">revert</span><span class="p">(</span><span class="nx">r</span><span class="p">)</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">toString</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">b</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">s</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mf">0</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="s2">"-"</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">negate</span><span class="p">().</span><span class="nx">toString</span><span class="p">(</span><span class="nx">b</span><span class="p">);</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">k</span><span class="p">;</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="mf">16</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">b</span><span class="p">)</span><span class="w"> </span><span class="nx">k</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">4</span><span class="p">;</span>
<span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="mf">8</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">b</span><span class="p">)</span><span class="w"> </span><span class="nx">k</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">3</span><span class="p">;</span>
<span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="mf">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">b</span><span class="p">)</span><span class="w"> </span><span class="nx">k</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">1</span><span class="p">;</span>
<span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="mf">32</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">b</span><span class="p">)</span><span class="w"> </span><span class="nx">k</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">5</span><span class="p">;</span>
<span class="w"> </span><span class="k">else</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="mf">4</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nx">b</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">toRadix</span><span class="p">(</span><span class="nx">b</span><span class="p">);</span>
<span class="w"> </span><span class="nx">k</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">2</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">d</span><span class="p">,</span><span class="w"> </span><span class="nx">km</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="mf">1</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="nx">k</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span>
<span class="w"> </span><span class="nx">m</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">!</span><span class="mf">1</span><span class="p">,</span>
<span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span>
<span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="p">,</span>
<span class="w"> </span><span class="nx">p</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DB</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DB</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="nx">k</span><span class="p">;</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">i</span><span class="o">--</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">0</span><span class="p">)</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="nx">p</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DB</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">d</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="nx">p</span><span class="p">)</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">m</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">!</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">int2char</span><span class="p">(</span><span class="nx">d</span><span class="p">));</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="mf">0</span><span class="p">;)</span><span class="w"> </span><span class="nx">p</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">k</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="p">(</span><span class="nx">d</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="k">this</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="p">(</span><span class="mf">1</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="nx">p</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="nx">k</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">p</span><span class="p">,</span><span class="w"> </span><span class="nx">d</span><span class="w"> </span><span class="o">|=</span><span class="w"> </span><span class="k">this</span><span class="p">[</span><span class="o">--</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="p">(</span><span class="nx">p</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DB</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">k</span><span class="p">))</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">d</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="p">(</span><span class="nx">p</span><span class="w"> </span><span class="o">-=</span><span class="w"> </span><span class="nx">k</span><span class="p">)</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="nx">km</span><span class="p">,</span><span class="w"> </span><span class="nx">p</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">p</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DB</span><span class="p">,</span><span class="w"> </span><span class="o">--</span><span class="nx">i</span><span class="p">)),</span><span class="w"> </span><span class="nx">d</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">m</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">!</span><span class="mf">0</span><span class="p">),</span><span class="w"> </span><span class="nx">m</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">r</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="nx">int2char</span><span class="p">(</span><span class="nx">d</span><span class="p">));</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">m</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="s2">"0"</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">negate</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">()</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">nbi</span><span class="p">();</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">ZERO</span><span class="p">.</span><span class="nx">subTo</span><span class="p">(</span><span class="k">this</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">),</span><span class="w"> </span><span class="nx">r</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">abs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">()</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">s</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">negate</span><span class="p">()</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="k">this</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">compareTo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">a</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">s</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">a</span><span class="p">.</span><span class="nx">s</span><span class="p">;</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="mf">0</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nx">r</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">r</span><span class="p">;</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="p">;</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="mf">0</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="p">(</span><span class="nx">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">a</span><span class="p">.</span><span class="nx">t</span><span class="p">))</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">s</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="o">-</span><span class="nx">r</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="nx">r</span><span class="p">;</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(;</span><span class="w"> </span><span class="o">--</span><span class="nx">i</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="mf">0</span><span class="p">;)</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="mf">0</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="p">(</span><span class="nx">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">a</span><span class="p">[</span><span class="nx">i</span><span class="p">]))</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">r</span><span class="p">;</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mf">0</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">bitLength</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">()</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DB</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">nbits</span><span class="p">(</span><span class="k">this</span><span class="p">[</span><span class="k">this</span><span class="p">.</span><span class="nx">t</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">]</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">s</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">DM</span><span class="p">)</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">mod</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">a</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">nbi</span><span class="p">();</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">abs</span><span class="p">().</span><span class="nx">divRemTo</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">),</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">s</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">compareTo</span><span class="p">(</span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">ZERO</span><span class="p">)</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="nx">a</span><span class="p">.</span><span class="nx">subTo</span><span class="p">(</span><span class="nx">r</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">),</span><span class="w"> </span><span class="nx">r</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">modPowInt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">e</span><span class="p">,</span><span class="w"> </span><span class="nx">m</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">z</span><span class="p">;</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">z</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">e</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mf">256</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="nx">m</span><span class="p">.</span><span class="nx">isEven</span><span class="p">()</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Classic</span><span class="p">(</span><span class="nx">m</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Montgomery</span><span class="p">(</span><span class="nx">m</span><span class="p">),</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">exp</span><span class="p">(</span><span class="nx">e</span><span class="p">,</span><span class="w"> </span><span class="nx">z</span><span class="p">)</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">ZERO</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">nbv</span><span class="p">(</span><span class="mf">0</span><span class="p">),</span><span class="w"> </span><span class="nx">BigInteger</span><span class="p">.</span><span class="nx">ONE</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">nbv</span><span class="p">(</span><span class="mf">1</span><span class="p">),</span><span class="w"> </span><span class="nx">Arcfour</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">init</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">key</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">i</span><span class="p">,</span><span class="w"> </span><span class="nx">j</span><span class="p">,</span><span class="w"> </span><span class="nx">t</span><span class="p">;</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mf">256</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">S</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">i</span><span class="p">;</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="nx">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mf">256</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="nx">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">j</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">S</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">key</span><span class="p">[</span><span class="nx">i</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="nx">key</span><span class="p">.</span><span class="nx">length</span><span class="p">]</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">255</span><span class="p">,</span><span class="w"> </span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">S</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">S</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">S</span><span class="p">[</span><span class="nx">j</span><span class="p">],</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">S</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">t</span><span class="p">;</span>
<span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">Arcfour</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">next</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">()</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">t</span><span class="p">;</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">255</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">j</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">S</span><span class="p">[</span><span class="k">this</span><span class="p">.</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">255</span><span class="p">,</span><span class="w"> </span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">S</span><span class="p">[</span><span class="k">this</span><span class="p">.</span><span class="nx">i</span><span class="p">],</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">S</span><span class="p">[</span><span class="k">this</span><span class="p">.</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">S</span><span class="p">[</span><span class="k">this</span><span class="p">.</span><span class="nx">j</span><span class="p">],</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">S</span><span class="p">[</span><span class="k">this</span><span class="p">.</span><span class="nx">j</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">t</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">S</span><span class="p">[</span><span class="nx">t</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">S</span><span class="p">[</span><span class="k">this</span><span class="p">.</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">255</span><span class="p">]</span>
<span class="w"> </span><span class="p">};</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">rng_state</span><span class="p">,</span><span class="w"> </span><span class="nx">rng_pool</span><span class="p">,</span><span class="w"> </span><span class="nx">rng_pptr</span><span class="p">,</span><span class="w"> </span><span class="nx">rng_psize</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">256</span><span class="p">;</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="kc">null</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">rng_pool</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">rng_pool</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">,</span><span class="w"> </span><span class="nx">rng_pptr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">t</span><span class="p">;</span>
<span class="w"> </span><span class="cm">/*if (window.crypto && window.crypto.getRandomValues)</span>
<span class="cm"> {</span>
<span class="cm"> var ua = new Uint8Array(32);</span>
<span class="cm"> for (window.crypto.getRandomValues(ua), t = 0; t < 32; ++t) rng_pool[rng_pptr++] = ua[t]</span>
<span class="cm"> }*/</span>
<span class="w"> </span><span class="cm">/*if ("Netscape" == navigator.appName && navigator.appVersion < "5" && window.crypto)</span>
<span class="cm"> {</span>
<span class="cm"> var z = window.crypto.random(32);</span>
<span class="cm"> for (t = 0; t < z.length; ++t) rng_pool[rng_pptr++] = 255 & z.charCodeAt(t)</span>
<span class="cm"> }*/</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(;</span><span class="w"> </span><span class="nx">rng_pptr</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">rng_psize</span><span class="p">;)</span><span class="w"> </span><span class="nx">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">floor</span><span class="p">(</span><span class="mf">65536</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">()),</span><span class="w"> </span><span class="nx">rng_pool</span><span class="p">[</span><span class="nx">rng_pptr</span><span class="o">++</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">t</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">8</span><span class="p">,</span><span class="w"> </span><span class="nx">rng_pool</span><span class="p">[</span><span class="nx">rng_pptr</span><span class="o">++</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">255</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="nx">t</span><span class="p">;</span>
<span class="w"> </span><span class="nx">rng_pptr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">rng_seed_time</span><span class="p">()</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="nx">SecureRandom</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">nextBytes</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">ba</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">i</span><span class="p">;</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">ba</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="nx">ba</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">rng_get_byte</span><span class="p">()</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">RSAKey</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">doPublic</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">x</span><span class="p">.</span><span class="nx">modPowInt</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">e</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">n</span><span class="p">)</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">RSAKey</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">setPublic</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">N</span><span class="p">,</span><span class="w"> </span><span class="nx">E</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kc">null</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nx">N</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="kc">null</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nx">E</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="nx">N</span><span class="p">.</span><span class="nx">length</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="nx">E</span><span class="p">.</span><span class="nx">length</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">parseBigInt</span><span class="p">(</span><span class="nx">N</span><span class="p">,</span><span class="w"> </span><span class="mf">16</span><span class="p">),</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">e</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">parseInt</span><span class="p">(</span><span class="nx">E</span><span class="p">,</span><span class="w"> </span><span class="mf">16</span><span class="p">))</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="cm">/*alert*/</span><span class="nx">print</span><span class="p">(</span><span class="s2">"Invalid RSA public key"</span><span class="p">)</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">RSAKey</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">encrypt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">text</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">m</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">pkcs1pad2</span><span class="p">(</span><span class="nx">text</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">n</span><span class="p">.</span><span class="nx">bitLength</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">7</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="mf">3</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="kc">null</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">m</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="kc">null</span><span class="p">;</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">doPublic</span><span class="p">(</span><span class="nx">m</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="kc">null</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">c</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="kc">null</span><span class="p">;</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">h</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">toString</span><span class="p">(</span><span class="mf">16</span><span class="p">);</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="p">(</span><span class="mf">1</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="nx">h</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="nx">h</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="s2">"0"</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">h</span>
<span class="w"> </span><span class="p">};</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">rsaObj</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">RSAKey</span><span class="p">,</span>
<span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">nn</span><span class="p">,</span>
<span class="w"> </span><span class="nx">e</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">ee</span><span class="p">;</span>
<span class="w"> </span><span class="nx">rsaObj</span><span class="p">.</span><span class="nx">setPublic</span><span class="p">(</span><span class="nx">n</span><span class="p">,</span><span class="w"> </span><span class="nx">e</span><span class="p">);</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">rsaObj</span><span class="p">.</span><span class="nx">encrypt</span><span class="p">(</span><span class="nx">val</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="mf">256</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nx">result</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">var</span><span class="w"> </span><span class="nx">l</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">abs</span><span class="p">(</span><span class="mf">256</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">result</span><span class="p">.</span><span class="nx">length</span><span class="p">),</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">l</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"0"</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">result</span><span class="p">;</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">result</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">$</span><span class="p">.</span><span class="nx">des</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">key</span><span class="p">,</span><span class="w"> </span><span class="nx">message</span><span class="p">,</span><span class="w"> </span><span class="nx">encrypt</span><span class="p">,</span><span class="w"> </span><span class="nx">mode</span><span class="p">,</span><span class="w"> </span><span class="nx">iv</span><span class="p">,</span><span class="w"> </span><span class="nx">padding</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">encrypt</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">message</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">unescape</span><span class="p">(</span><span class="nb">encodeURIComponent</span><span class="p">(</span><span class="nx">message</span><span class="p">)));</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">i</span><span class="p">,</span><span class="w"> </span><span class="nx">j</span><span class="p">,</span><span class="w"> </span><span class="nx">temp</span><span class="p">,</span><span class="w"> </span><span class="nx">right1</span><span class="p">,</span><span class="w"> </span><span class="nx">right2</span><span class="p">,</span><span class="w"> </span><span class="nx">left</span><span class="p">,</span><span class="w"> </span><span class="nx">right</span><span class="p">,</span><span class="w"> </span><span class="nx">looping</span><span class="p">,</span><span class="w"> </span><span class="nx">cbcleft</span><span class="p">,</span><span class="w"> </span><span class="nx">cbcleft2</span><span class="p">,</span><span class="w"> </span><span class="nx">cbcright</span><span class="p">,</span><span class="w"> </span><span class="nx">cbcright2</span><span class="p">,</span><span class="w"> </span><span class="nx">endloop</span><span class="p">,</span><span class="w"> </span><span class="nx">loopinc</span><span class="p">,</span><span class="w"> </span><span class="nx">spfunction1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">16843776</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">65536</span><span class="p">,</span><span class="w"> </span><span class="mf">16843780</span><span class="p">,</span><span class="w"> </span><span class="mf">16842756</span><span class="p">,</span><span class="w"> </span><span class="mf">66564</span><span class="p">,</span><span class="w"> </span><span class="mf">4</span><span class="p">,</span><span class="w"> </span><span class="mf">65536</span><span class="p">,</span><span class="w"> </span><span class="mf">1024</span><span class="p">,</span><span class="w"> </span><span class="mf">16843776</span><span class="p">,</span><span class="w"> </span><span class="mf">16843780</span><span class="p">,</span><span class="w"> </span><span class="mf">1024</span><span class="p">,</span><span class="w"> </span><span class="mf">16778244</span><span class="p">,</span><span class="w"> </span><span class="mf">16842756</span><span class="p">,</span><span class="w"> </span><span class="mf">16777216</span><span class="p">,</span><span class="w"> </span><span class="mf">4</span><span class="p">,</span><span class="w"> </span><span class="mf">1028</span><span class="p">,</span><span class="w"> </span><span class="mf">16778240</span><span class="p">,</span><span class="w"> </span><span class="mf">16778240</span><span class="p">,</span><span class="w"> </span><span class="mf">66560</span><span class="p">,</span><span class="w"> </span><span class="mf">66560</span><span class="p">,</span><span class="w"> </span><span class="mf">16842752</span><span class="p">,</span><span class="w"> </span><span class="mf">16842752</span><span class="p">,</span><span class="w"> </span><span class="mf">16778244</span><span class="p">,</span><span class="w"> </span><span class="mf">65540</span><span class="p">,</span><span class="w"> </span><span class="mf">16777220</span><span class="p">,</span><span class="w"> </span><span class="mf">16777220</span><span class="p">,</span><span class="w"> </span><span class="mf">65540</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">1028</span><span class="p">,</span><span class="w"> </span><span class="mf">66564</span><span class="p">,</span><span class="w"> </span><span class="mf">16777216</span><span class="p">,</span><span class="w"> </span><span class="mf">65536</span><span class="p">,</span><span class="w"> </span><span class="mf">16843780</span><span class="p">,</span><span class="w"> </span><span class="mf">4</span><span class="p">,</span><span class="w"> </span><span class="mf">16842752</span><span class="p">,</span><span class="w"> </span><span class="mf">16843776</span><span class="p">,</span><span class="w"> </span><span class="mf">16777216</span><span class="p">,</span><span class="w"> </span><span class="mf">16777216</span><span class="p">,</span><span class="w"> </span><span class="mf">1024</span><span class="p">,</span><span class="w"> </span><span class="mf">16842756</span><span class="p">,</span><span class="w"> </span><span class="mf">65536</span><span class="p">,</span><span class="w"> </span><span class="mf">66560</span><span class="p">,</span><span class="w"> </span><span class="mf">16777220</span><span class="p">,</span><span class="w"> </span><span class="mf">1024</span><span class="p">,</span><span class="w"> </span><span class="mf">4</span><span class="p">,</span><span class="w"> </span><span class="mf">16778244</span><span class="p">,</span><span class="w"> </span><span class="mf">66564</span><span class="p">,</span><span class="w"> </span><span class="mf">16843780</span><span class="p">,</span><span class="w"> </span><span class="mf">65540</span><span class="p">,</span><span class="w"> </span><span class="mf">16842752</span><span class="p">,</span><span class="w"> </span><span class="mf">16778244</span><span class="p">,</span><span class="w"> </span><span class="mf">16777220</span><span class="p">,</span><span class="w"> </span><span class="mf">1028</span><span class="p">,</span><span class="w"> </span><span class="mf">66564</span><span class="p">,</span><span class="w"> </span><span class="mf">16843776</span><span class="p">,</span><span class="w"> </span><span class="mf">1028</span><span class="p">,</span><span class="w"> </span><span class="mf">16778240</span><span class="p">,</span><span class="w"> </span><span class="mf">16778240</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">65540</span><span class="p">,</span><span class="w"> </span><span class="mf">66560</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">16842756</span><span class="p">),</span>
<span class="w"> </span><span class="nx">spfunction2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="o">-</span><span class="mf">2146402272</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2147450880</span><span class="p">,</span><span class="w"> </span><span class="mf">32768</span><span class="p">,</span><span class="w"> </span><span class="mf">1081376</span><span class="p">,</span><span class="w"> </span><span class="mf">1048576</span><span class="p">,</span><span class="w"> </span><span class="mf">32</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2146435040</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2147450848</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2147483616</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2146402272</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2146402304</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2147483648</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2147450880</span><span class="p">,</span><span class="w"> </span><span class="mf">1048576</span><span class="p">,</span><span class="w"> </span><span class="mf">32</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2146435040</span><span class="p">,</span><span class="w"> </span><span class="mf">1081344</span><span class="p">,</span><span class="w"> </span><span class="mf">1048608</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2147450848</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2147483648</span><span class="p">,</span><span class="w"> </span><span class="mf">32768</span><span class="p">,</span><span class="w"> </span><span class="mf">1081376</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2146435072</span><span class="p">,</span><span class="w"> </span><span class="mf">1048608</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2147483616</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">1081344</span><span class="p">,</span><span class="w"> </span><span class="mf">32800</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2146402304</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2146435072</span><span class="p">,</span><span class="w"> </span><span class="mf">32800</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">1081376</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2146435040</span><span class="p">,</span><span class="w"> </span><span class="mf">1048576</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2147450848</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2146435072</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2146402304</span><span class="p">,</span><span class="w"> </span><span class="mf">32768</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2146435072</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2147450880</span><span class="p">,</span><span class="w"> </span><span class="mf">32</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2146402272</span><span class="p">,</span><span class="w"> </span><span class="mf">1081376</span><span class="p">,</span><span class="w"> </span><span class="mf">32</span><span class="p">,</span><span class="w"> </span><span class="mf">32768</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2147483648</span><span class="p">,</span><span class="w"> </span><span class="mf">32800</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2146402304</span><span class="p">,</span><span class="w"> </span><span class="mf">1048576</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2147483616</span><span class="p">,</span><span class="w"> </span><span class="mf">1048608</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2147450848</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2147483616</span><span class="p">,</span><span class="w"> </span><span class="mf">1048608</span><span class="p">,</span><span class="w"> </span><span class="mf">1081344</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2147450880</span><span class="p">,</span><span class="w"> </span><span class="mf">32800</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2147483648</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2146435040</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2146402272</span><span class="p">,</span><span class="w"> </span><span class="mf">1081344</span><span class="p">),</span>
<span class="w"> </span><span class="nx">spfunction3</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">520</span><span class="p">,</span><span class="w"> </span><span class="mf">134349312</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">134348808</span><span class="p">,</span><span class="w"> </span><span class="mf">134218240</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">131592</span><span class="p">,</span><span class="w"> </span><span class="mf">134218240</span><span class="p">,</span><span class="w"> </span><span class="mf">131080</span><span class="p">,</span><span class="w"> </span><span class="mf">134217736</span><span class="p">,</span><span class="w"> </span><span class="mf">134217736</span><span class="p">,</span><span class="w"> </span><span class="mf">131072</span><span class="p">,</span><span class="w"> </span><span class="mf">134349320</span><span class="p">,</span><span class="w"> </span><span class="mf">131080</span><span class="p">,</span><span class="w"> </span><span class="mf">134348800</span><span class="p">,</span><span class="w"> </span><span class="mf">520</span><span class="p">,</span><span class="w"> </span><span class="mf">134217728</span><span class="p">,</span><span class="w"> </span><span class="mf">8</span><span class="p">,</span><span class="w"> </span><span class="mf">134349312</span><span class="p">,</span><span class="w"> </span><span class="mf">512</span><span class="p">,</span><span class="w"> </span><span class="mf">131584</span><span class="p">,</span><span class="w"> </span><span class="mf">134348800</span><span class="p">,</span><span class="w"> </span><span class="mf">134348808</span><span class="p">,</span><span class="w"> </span><span class="mf">131592</span><span class="p">,</span><span class="w"> </span><span class="mf">134218248</span><span class="p">,</span><span class="w"> </span><span class="mf">131584</span><span class="p">,</span><span class="w"> </span><span class="mf">131072</span><span class="p">,</span><span class="w"> </span><span class="mf">134218248</span><span class="p">,</span><span class="w"> </span><span class="mf">8</span><span class="p">,</span><span class="w"> </span><span class="mf">134349320</span><span class="p">,</span><span class="w"> </span><span class="mf">512</span><span class="p">,</span><span class="w"> </span><span class="mf">134217728</span><span class="p">,</span><span class="w"> </span><span class="mf">134349312</span><span class="p">,</span><span class="w"> </span><span class="mf">134217728</span><span class="p">,</span><span class="w"> </span><span class="mf">131080</span><span class="p">,</span><span class="w"> </span><span class="mf">520</span><span class="p">,</span><span class="w"> </span><span class="mf">131072</span><span class="p">,</span><span class="w"> </span><span class="mf">134349312</span><span class="p">,</span><span class="w"> </span><span class="mf">134218240</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">512</span><span class="p">,</span><span class="w"> </span><span class="mf">131080</span><span class="p">,</span><span class="w"> </span><span class="mf">134349320</span><span class="p">,</span><span class="w"> </span><span class="mf">134218240</span><span class="p">,</span><span class="w"> </span><span class="mf">134217736</span><span class="p">,</span><span class="w"> </span><span class="mf">512</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">134348808</span><span class="p">,</span><span class="w"> </span><span class="mf">134218248</span><span class="p">,</span><span class="w"> </span><span class="mf">131072</span><span class="p">,</span><span class="w"> </span><span class="mf">134217728</span><span class="p">,</span><span class="w"> </span><span class="mf">134349320</span><span class="p">,</span><span class="w"> </span><span class="mf">8</span><span class="p">,</span><span class="w"> </span><span class="mf">131592</span><span class="p">,</span><span class="w"> </span><span class="mf">131584</span><span class="p">,</span><span class="w"> </span><span class="mf">134217736</span><span class="p">,</span><span class="w"> </span><span class="mf">134348800</span><span class="p">,</span><span class="w"> </span><span class="mf">134218248</span><span class="p">,</span><span class="w"> </span><span class="mf">520</span><span class="p">,</span><span class="w"> </span><span class="mf">134348800</span><span class="p">,</span><span class="w"> </span><span class="mf">131592</span><span class="p">,</span><span class="w"> </span><span class="mf">8</span><span class="p">,</span><span class="w"> </span><span class="mf">134348808</span><span class="p">,</span><span class="w"> </span><span class="mf">131584</span><span class="p">),</span>
<span class="w"> </span><span class="nx">spfunction4</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">8396801</span><span class="p">,</span><span class="w"> </span><span class="mf">8321</span><span class="p">,</span><span class="w"> </span><span class="mf">8321</span><span class="p">,</span><span class="w"> </span><span class="mf">128</span><span class="p">,</span><span class="w"> </span><span class="mf">8396928</span><span class="p">,</span><span class="w"> </span><span class="mf">8388737</span><span class="p">,</span><span class="w"> </span><span class="mf">8388609</span><span class="p">,</span><span class="w"> </span><span class="mf">8193</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">8396800</span><span class="p">,</span><span class="w"> </span><span class="mf">8396800</span><span class="p">,</span><span class="w"> </span><span class="mf">8396929</span><span class="p">,</span><span class="w"> </span><span class="mf">129</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">8388736</span><span class="p">,</span><span class="w"> </span><span class="mf">8388609</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">8192</span><span class="p">,</span><span class="w"> </span><span class="mf">8388608</span><span class="p">,</span><span class="w"> </span><span class="mf">8396801</span><span class="p">,</span><span class="w"> </span><span class="mf">128</span><span class="p">,</span><span class="w"> </span><span class="mf">8388608</span><span class="p">,</span><span class="w"> </span><span class="mf">8193</span><span class="p">,</span><span class="w"> </span><span class="mf">8320</span><span class="p">,</span><span class="w"> </span><span class="mf">8388737</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">8320</span><span class="p">,</span><span class="w"> </span><span class="mf">8388736</span><span class="p">,</span><span class="w"> </span><span class="mf">8192</span><span class="p">,</span><span class="w"> </span><span class="mf">8396928</span><span class="p">,</span><span class="w"> </span><span class="mf">8396929</span><span class="p">,</span><span class="w"> </span><span class="mf">129</span><span class="p">,</span><span class="w"> </span><span class="mf">8388736</span><span class="p">,</span><span class="w"> </span><span class="mf">8388609</span><span class="p">,</span><span class="w"> </span><span class="mf">8396800</span><span class="p">,</span><span class="w"> </span><span class="mf">8396929</span><span class="p">,</span><span class="w"> </span><span class="mf">129</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">8396800</span><span class="p">,</span><span class="w"> </span><span class="mf">8320</span><span class="p">,</span><span class="w"> </span><span class="mf">8388736</span><span class="p">,</span><span class="w"> </span><span class="mf">8388737</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">8396801</span><span class="p">,</span><span class="w"> </span><span class="mf">8321</span><span class="p">,</span><span class="w"> </span><span class="mf">8321</span><span class="p">,</span><span class="w"> </span><span class="mf">128</span><span class="p">,</span><span class="w"> </span><span class="mf">8396929</span><span class="p">,</span><span class="w"> </span><span class="mf">129</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">8192</span><span class="p">,</span><span class="w"> </span><span class="mf">8388609</span><span class="p">,</span><span class="w"> </span><span class="mf">8193</span><span class="p">,</span><span class="w"> </span><span class="mf">8396928</span><span class="p">,</span><span class="w"> </span><span class="mf">8388737</span><span class="p">,</span><span class="w"> </span><span class="mf">8193</span><span class="p">,</span><span class="w"> </span><span class="mf">8320</span><span class="p">,</span><span class="w"> </span><span class="mf">8388608</span><span class="p">,</span><span class="w"> </span><span class="mf">8396801</span><span class="p">,</span><span class="w"> </span><span class="mf">128</span><span class="p">,</span><span class="w"> </span><span class="mf">8388608</span><span class="p">,</span><span class="w"> </span><span class="mf">8192</span><span class="p">,</span><span class="w"> </span><span class="mf">8396928</span><span class="p">),</span>
<span class="w"> </span><span class="nx">spfunction5</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">256</span><span class="p">,</span><span class="w"> </span><span class="mf">34078976</span><span class="p">,</span><span class="w"> </span><span class="mf">34078720</span><span class="p">,</span><span class="w"> </span><span class="mf">1107296512</span><span class="p">,</span><span class="w"> </span><span class="mf">524288</span><span class="p">,</span><span class="w"> </span><span class="mf">256</span><span class="p">,</span><span class="w"> </span><span class="mf">1073741824</span><span class="p">,</span><span class="w"> </span><span class="mf">34078720</span><span class="p">,</span><span class="w"> </span><span class="mf">1074266368</span><span class="p">,</span><span class="w"> </span><span class="mf">524288</span><span class="p">,</span><span class="w"> </span><span class="mf">33554688</span><span class="p">,</span><span class="w"> </span><span class="mf">1074266368</span><span class="p">,</span><span class="w"> </span><span class="mf">1107296512</span><span class="p">,</span><span class="w"> </span><span class="mf">1107820544</span><span class="p">,</span><span class="w"> </span><span class="mf">524544</span><span class="p">,</span><span class="w"> </span><span class="mf">1073741824</span><span class="p">,</span><span class="w"> </span><span class="mf">33554432</span><span class="p">,</span><span class="w"> </span><span class="mf">1074266112</span><span class="p">,</span><span class="w"> </span><span class="mf">1074266112</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">1073742080</span><span class="p">,</span><span class="w"> </span><span class="mf">1107820800</span><span class="p">,</span><span class="w"> </span><span class="mf">1107820800</span><span class="p">,</span><span class="w"> </span><span class="mf">33554688</span><span class="p">,</span><span class="w"> </span><span class="mf">1107820544</span><span class="p">,</span><span class="w"> </span><span class="mf">1073742080</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">1107296256</span><span class="p">,</span><span class="w"> </span><span class="mf">34078976</span><span class="p">,</span><span class="w"> </span><span class="mf">33554432</span><span class="p">,</span><span class="w"> </span><span class="mf">1107296256</span><span class="p">,</span><span class="w"> </span><span class="mf">524544</span><span class="p">,</span><span class="w"> </span><span class="mf">524288</span><span class="p">,</span><span class="w"> </span><span class="mf">1107296512</span><span class="p">,</span><span class="w"> </span><span class="mf">256</span><span class="p">,</span><span class="w"> </span><span class="mf">33554432</span><span class="p">,</span><span class="w"> </span><span class="mf">1073741824</span><span class="p">,</span><span class="w"> </span><span class="mf">34078720</span><span class="p">,</span><span class="w"> </span><span class="mf">1107296512</span><span class="p">,</span><span class="w"> </span><span class="mf">1074266368</span><span class="p">,</span><span class="w"> </span><span class="mf">33554688</span><span class="p">,</span><span class="w"> </span><span class="mf">1073741824</span><span class="p">,</span><span class="w"> </span><span class="mf">1107820544</span><span class="p">,</span><span class="w"> </span><span class="mf">34078976</span><span class="p">,</span><span class="w"> </span><span class="mf">1074266368</span><span class="p">,</span><span class="w"> </span><span class="mf">256</span><span class="p">,</span><span class="w"> </span><span class="mf">33554432</span><span class="p">,</span><span class="w"> </span><span class="mf">1107820544</span><span class="p">,</span><span class="w"> </span><span class="mf">1107820800</span><span class="p">,</span><span class="w"> </span><span class="mf">524544</span><span class="p">,</span><span class="w"> </span><span class="mf">1107296256</span><span class="p">,</span><span class="w"> </span><span class="mf">1107820800</span><span class="p">,</span><span class="w"> </span><span class="mf">34078720</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">1074266112</span><span class="p">,</span><span class="w"> </span><span class="mf">1107296256</span><span class="p">,</span><span class="w"> </span><span class="mf">524544</span><span class="p">,</span><span class="w"> </span><span class="mf">33554688</span><span class="p">,</span><span class="w"> </span><span class="mf">1073742080</span><span class="p">,</span><span class="w"> </span><span class="mf">524288</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">1074266112</span><span class="p">,</span><span class="w"> </span><span class="mf">34078976</span><span class="p">,</span><span class="w"> </span><span class="mf">1073742080</span><span class="p">),</span>
<span class="w"> </span><span class="nx">spfunction6</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">536870928</span><span class="p">,</span><span class="w"> </span><span class="mf">541065216</span><span class="p">,</span><span class="w"> </span><span class="mf">16384</span><span class="p">,</span><span class="w"> </span><span class="mf">541081616</span><span class="p">,</span><span class="w"> </span><span class="mf">541065216</span><span class="p">,</span><span class="w"> </span><span class="mf">16</span><span class="p">,</span><span class="w"> </span><span class="mf">541081616</span><span class="p">,</span><span class="w"> </span><span class="mf">4194304</span><span class="p">,</span><span class="w"> </span><span class="mf">536887296</span><span class="p">,</span><span class="w"> </span><span class="mf">4210704</span><span class="p">,</span><span class="w"> </span><span class="mf">4194304</span><span class="p">,</span><span class="w"> </span><span class="mf">536870928</span><span class="p">,</span><span class="w"> </span><span class="mf">4194320</span><span class="p">,</span><span class="w"> </span><span class="mf">536887296</span><span class="p">,</span><span class="w"> </span><span class="mf">536870912</span><span class="p">,</span><span class="w"> </span><span class="mf">16400</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">4194320</span><span class="p">,</span><span class="w"> </span><span class="mf">536887312</span><span class="p">,</span><span class="w"> </span><span class="mf">16384</span><span class="p">,</span><span class="w"> </span><span class="mf">4210688</span><span class="p">,</span><span class="w"> </span><span class="mf">536887312</span><span class="p">,</span><span class="w"> </span><span class="mf">16</span><span class="p">,</span><span class="w"> </span><span class="mf">541065232</span><span class="p">,</span><span class="w"> </span><span class="mf">541065232</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">4210704</span><span class="p">,</span><span class="w"> </span><span class="mf">541081600</span><span class="p">,</span><span class="w"> </span><span class="mf">16400</span><span class="p">,</span><span class="w"> </span><span class="mf">4210688</span><span class="p">,</span><span class="w"> </span><span class="mf">541081600</span><span class="p">,</span><span class="w"> </span><span class="mf">536870912</span><span class="p">,</span><span class="w"> </span><span class="mf">536887296</span><span class="p">,</span><span class="w"> </span><span class="mf">16</span><span class="p">,</span><span class="w"> </span><span class="mf">541065232</span><span class="p">,</span><span class="w"> </span><span class="mf">4210688</span><span class="p">,</span><span class="w"> </span><span class="mf">541081616</span><span class="p">,</span><span class="w"> </span><span class="mf">4194304</span><span class="p">,</span><span class="w"> </span><span class="mf">16400</span><span class="p">,</span><span class="w"> </span><span class="mf">536870928</span><span class="p">,</span><span class="w"> </span><span class="mf">4194304</span><span class="p">,</span><span class="w"> </span><span class="mf">536887296</span><span class="p">,</span><span class="w"> </span><span class="mf">536870912</span><span class="p">,</span><span class="w"> </span><span class="mf">16400</span><span class="p">,</span><span class="w"> </span><span class="mf">536870928</span><span class="p">,</span><span class="w"> </span><span class="mf">541081616</span><span class="p">,</span><span class="w"> </span><span class="mf">4210688</span><span class="p">,</span><span class="w"> </span><span class="mf">541065216</span><span class="p">,</span><span class="w"> </span><span class="mf">4210704</span><span class="p">,</span><span class="w"> </span><span class="mf">541081600</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">541065232</span><span class="p">,</span><span class="w"> </span><span class="mf">16</span><span class="p">,</span><span class="w"> </span><span class="mf">16384</span><span class="p">,</span><span class="w"> </span><span class="mf">541065216</span><span class="p">,</span><span class="w"> </span><span class="mf">4210704</span><span class="p">,</span><span class="w"> </span><span class="mf">16384</span><span class="p">,</span><span class="w"> </span><span class="mf">4194320</span><span class="p">,</span><span class="w"> </span><span class="mf">536887312</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">541081600</span><span class="p">,</span><span class="w"> </span><span class="mf">536870912</span><span class="p">,</span><span class="w"> </span><span class="mf">4194320</span><span class="p">,</span><span class="w"> </span><span class="mf">536887312</span><span class="p">),</span>
<span class="w"> </span><span class="nx">spfunction7</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">2097152</span><span class="p">,</span><span class="w"> </span><span class="mf">69206018</span><span class="p">,</span><span class="w"> </span><span class="mf">67110914</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">2048</span><span class="p">,</span><span class="w"> </span><span class="mf">67110914</span><span class="p">,</span><span class="w"> </span><span class="mf">2099202</span><span class="p">,</span><span class="w"> </span><span class="mf">69208064</span><span class="p">,</span><span class="w"> </span><span class="mf">69208066</span><span class="p">,</span><span class="w"> </span><span class="mf">2097152</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">67108866</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="mf">67108864</span><span class="p">,</span><span class="w"> </span><span class="mf">69206018</span><span class="p">,</span><span class="w"> </span><span class="mf">2050</span><span class="p">,</span><span class="w"> </span><span class="mf">67110912</span><span class="p">,</span><span class="w"> </span><span class="mf">2099202</span><span class="p">,</span><span class="w"> </span><span class="mf">2097154</span><span class="p">,</span><span class="w"> </span><span class="mf">67110912</span><span class="p">,</span><span class="w"> </span><span class="mf">67108866</span><span class="p">,</span><span class="w"> </span><span class="mf">69206016</span><span class="p">,</span><span class="w"> </span><span class="mf">69208064</span><span class="p">,</span><span class="w"> </span><span class="mf">2097154</span><span class="p">,</span><span class="w"> </span><span class="mf">69206016</span><span class="p">,</span><span class="w"> </span><span class="mf">2048</span><span class="p">,</span><span class="w"> </span><span class="mf">2050</span><span class="p">,</span><span class="w"> </span><span class="mf">69208066</span><span class="p">,</span><span class="w"> </span><span class="mf">2099200</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="mf">67108864</span><span class="p">,</span><span class="w"> </span><span class="mf">2099200</span><span class="p">,</span><span class="w"> </span><span class="mf">67108864</span><span class="p">,</span><span class="w"> </span><span class="mf">2099200</span><span class="p">,</span><span class="w"> </span><span class="mf">2097152</span><span class="p">,</span><span class="w"> </span><span class="mf">67110914</span><span class="p">,</span><span class="w"> </span><span class="mf">67110914</span><span class="p">,</span><span class="w"> </span><span class="mf">69206018</span><span class="p">,</span><span class="w"> </span><span class="mf">69206018</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="mf">2097154</span><span class="p">,</span><span class="w"> </span><span class="mf">67108864</span><span class="p">,</span><span class="w"> </span><span class="mf">67110912</span><span class="p">,</span><span class="w"> </span><span class="mf">2097152</span><span class="p">,</span><span class="w"> </span><span class="mf">69208064</span><span class="p">,</span><span class="w"> </span><span class="mf">2050</span><span class="p">,</span><span class="w"> </span><span class="mf">2099202</span><span class="p">,</span><span class="w"> </span><span class="mf">69208064</span><span class="p">,</span><span class="w"> </span><span class="mf">2050</span><span class="p">,</span><span class="w"> </span><span class="mf">67108866</span><span class="p">,</span><span class="w"> </span><span class="mf">69208066</span><span class="p">,</span><span class="w"> </span><span class="mf">69206016</span><span class="p">,</span><span class="w"> </span><span class="mf">2099200</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="mf">69208066</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">2099202</span><span class="p">,</span><span class="w"> </span><span class="mf">69206016</span><span class="p">,</span><span class="w"> </span><span class="mf">2048</span><span class="p">,</span><span class="w"> </span><span class="mf">67108866</span><span class="p">,</span><span class="w"> </span><span class="mf">67110912</span><span class="p">,</span><span class="w"> </span><span class="mf">2048</span><span class="p">,</span><span class="w"> </span><span class="mf">2097154</span><span class="p">),</span>
<span class="w"> </span><span class="nx">spfunction8</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">268439616</span><span class="p">,</span><span class="w"> </span><span class="mf">4096</span><span class="p">,</span><span class="w"> </span><span class="mf">262144</span><span class="p">,</span><span class="w"> </span><span class="mf">268701760</span><span class="p">,</span><span class="w"> </span><span class="mf">268435456</span><span class="p">,</span><span class="w"> </span><span class="mf">268439616</span><span class="p">,</span><span class="w"> </span><span class="mf">64</span><span class="p">,</span><span class="w"> </span><span class="mf">268435456</span><span class="p">,</span><span class="w"> </span><span class="mf">262208</span><span class="p">,</span><span class="w"> </span><span class="mf">268697600</span><span class="p">,</span><span class="w"> </span><span class="mf">268701760</span><span class="p">,</span><span class="w"> </span><span class="mf">266240</span><span class="p">,</span><span class="w"> </span><span class="mf">268701696</span><span class="p">,</span><span class="w"> </span><span class="mf">266304</span><span class="p">,</span><span class="w"> </span><span class="mf">4096</span><span class="p">,</span><span class="w"> </span><span class="mf">64</span><span class="p">,</span><span class="w"> </span><span class="mf">268697600</span><span class="p">,</span><span class="w"> </span><span class="mf">268435520</span><span class="p">,</span><span class="w"> </span><span class="mf">268439552</span><span class="p">,</span><span class="w"> </span><span class="mf">4160</span><span class="p">,</span><span class="w"> </span><span class="mf">266240</span><span class="p">,</span><span class="w"> </span><span class="mf">262208</span><span class="p">,</span><span class="w"> </span><span class="mf">268697664</span><span class="p">,</span><span class="w"> </span><span class="mf">268701696</span><span class="p">,</span><span class="w"> </span><span class="mf">4160</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">268697664</span><span class="p">,</span><span class="w"> </span><span class="mf">268435520</span><span class="p">,</span><span class="w"> </span><span class="mf">268439552</span><span class="p">,</span><span class="w"> </span><span class="mf">266304</span><span class="p">,</span><span class="w"> </span><span class="mf">262144</span><span class="p">,</span><span class="w"> </span><span class="mf">266304</span><span class="p">,</span><span class="w"> </span><span class="mf">262144</span><span class="p">,</span><span class="w"> </span><span class="mf">268701696</span><span class="p">,</span><span class="w"> </span><span class="mf">4096</span><span class="p">,</span><span class="w"> </span><span class="mf">64</span><span class="p">,</span><span class="w"> </span><span class="mf">268697664</span><span class="p">,</span><span class="w"> </span><span class="mf">4096</span><span class="p">,</span><span class="w"> </span><span class="mf">266304</span><span class="p">,</span><span class="w"> </span><span class="mf">268439552</span><span class="p">,</span><span class="w"> </span><span class="mf">64</span><span class="p">,</span><span class="w"> </span><span class="mf">268435520</span><span class="p">,</span><span class="w"> </span><span class="mf">268697600</span><span class="p">,</span><span class="w"> </span><span class="mf">268697664</span><span class="p">,</span><span class="w"> </span><span class="mf">268435456</span><span class="p">,</span><span class="w"> </span><span class="mf">262144</span><span class="p">,</span><span class="w"> </span><span class="mf">268439616</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">268701760</span><span class="p">,</span><span class="w"> </span><span class="mf">262208</span><span class="p">,</span><span class="w"> </span><span class="mf">268435520</span><span class="p">,</span><span class="w"> </span><span class="mf">268697600</span><span class="p">,</span><span class="w"> </span><span class="mf">268439552</span><span class="p">,</span><span class="w"> </span><span class="mf">268439616</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">268701760</span><span class="p">,</span><span class="w"> </span><span class="mf">266240</span><span class="p">,</span><span class="w"> </span><span class="mf">266240</span><span class="p">,</span><span class="w"> </span><span class="mf">4160</span><span class="p">,</span><span class="w"> </span><span class="mf">4160</span><span class="p">,</span><span class="w"> </span><span class="mf">262208</span><span class="p">,</span><span class="w"> </span><span class="mf">268435456</span><span class="p">,</span><span class="w"> </span><span class="mf">268701696</span><span class="p">),</span>
<span class="w"> </span><span class="nx">keys</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">$</span><span class="p">.</span><span class="nx">des_createKeys</span><span class="p">(</span><span class="nx">key</span><span class="p">),</span>
<span class="w"> </span><span class="nx">m</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span>
<span class="w"> </span><span class="nx">len</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">message</span><span class="p">.</span><span class="nx">length</span><span class="p">,</span>
<span class="w"> </span><span class="nx">chunk</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span>
<span class="w"> </span><span class="nx">iterations</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">32</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">keys</span><span class="p">.</span><span class="nx">length</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="mf">3</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="mf">9</span><span class="p">;</span>
<span class="w"> </span><span class="nx">looping</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">3</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">iterations</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="nx">encrypt</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">32</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">30</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="nx">encrypt</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">32</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="mf">62</span><span class="p">,</span><span class="w"> </span><span class="mf">30</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="mf">64</span><span class="p">,</span><span class="w"> </span><span class="mf">96</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">94</span><span class="p">,</span><span class="w"> </span><span class="mf">62</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="mf">32</span><span class="p">,</span><span class="w"> </span><span class="mf">64</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="mf">30</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">2</span><span class="p">),</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">padding</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="nx">message</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="s2">" "</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">padding</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="nx">encrypt</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">8</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">len</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mf">8</span><span class="p">,</span><span class="w"> </span><span class="nx">message</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="nb">String</span><span class="p">.</span><span class="nx">fromCharCode</span><span class="p">(</span><span class="nx">temp</span><span class="p">,</span><span class="w"> </span><span class="nx">temp</span><span class="p">,</span><span class="w"> </span><span class="nx">temp</span><span class="p">,</span><span class="w"> </span><span class="nx">temp</span><span class="p">,</span><span class="w"> </span><span class="nx">temp</span><span class="p">,</span><span class="w"> </span><span class="nx">temp</span><span class="p">,</span><span class="w"> </span><span class="nx">temp</span><span class="p">,</span><span class="w"> </span><span class="nx">temp</span><span class="p">),</span><span class="w"> </span><span class="mf">8</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nx">temp</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">len</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mf">8</span><span class="p">))</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="nx">padding</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="p">(</span><span class="nx">message</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="s2">"\0\0\0\0\0\0\0\0"</span><span class="p">);</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span>
<span class="w"> </span><span class="nx">tempresult</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">""</span><span class="p">;</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="mf">1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">mode</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">cbcleft</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">iv</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">m</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">24</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">iv</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">m</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">iv</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">m</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">8</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">iv</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">m</span><span class="o">++</span><span class="p">),</span><span class="w"> </span><span class="nx">cbcright</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">iv</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">m</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">24</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">iv</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">m</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">iv</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">m</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">8</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">iv</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">m</span><span class="o">++</span><span class="p">),</span><span class="w"> </span><span class="nx">m</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">);</span><span class="w"> </span><span class="nx">m</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">len</span><span class="p">;)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="nx">left</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">message</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">m</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">24</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">message</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">m</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">message</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">m</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">8</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">message</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">m</span><span class="o">++</span><span class="p">),</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">message</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">m</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">24</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">message</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">m</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">message</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">m</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">8</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">message</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">m</span><span class="o">++</span><span class="p">),</span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">mode</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">encrypt</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="p">(</span><span class="nx">left</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">cbcleft</span><span class="p">,</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">cbcright</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">cbcleft2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">cbcleft</span><span class="p">,</span><span class="w"> </span><span class="nx">cbcright2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">cbcright</span><span class="p">,</span><span class="w"> </span><span class="nx">cbcleft</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">left</span><span class="p">,</span><span class="w"> </span><span class="nx">cbcright</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">right</span><span class="p">)),</span><span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="p">(</span><span class="nx">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">252645135</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="p">(</span><span class="nx">left</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">4</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="nx">right</span><span class="p">))</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">4</span><span class="p">,</span><span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="p">(</span><span class="nx">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">65535</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="p">(</span><span class="nx">left</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="p">(</span><span class="nx">right</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">temp</span><span class="p">)))</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">16</span><span class="p">,</span><span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">858993459</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="p">((</span><span class="nx">right</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">temp</span><span class="p">)</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="nx">left</span><span class="p">),</span><span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">16711935</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="p">((</span><span class="nx">right</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">temp</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">2</span><span class="p">)</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">8</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="nx">left</span><span class="p">),</span><span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="nx">left</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="p">(</span><span class="nx">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">1431655765</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="p">(</span><span class="nx">left</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="p">(</span><span class="nx">right</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">temp</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">8</span><span class="p">)))</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">1</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">31</span><span class="p">,</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="nx">right</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">temp</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">31</span><span class="p">,</span><span class="w"> </span><span class="nx">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">j</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">iterations</span><span class="p">;</span><span class="w"> </span><span class="nx">j</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mf">3</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="nx">endloop</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">looping</span><span class="p">[</span><span class="nx">j</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">1</span><span class="p">],</span><span class="w"> </span><span class="nx">loopinc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">looping</span><span class="p">[</span><span class="nx">j</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">2</span><span class="p">],</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">looping</span><span class="p">[</span><span class="nx">j</span><span class="p">];</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nx">endloop</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="nx">loopinc</span><span class="p">)</span><span class="w"> </span><span class="nx">right1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="nx">keys</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span><span class="w"> </span><span class="nx">right2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="nx">right</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">4</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">28</span><span class="p">)</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="nx">keys</span><span class="p">[</span><span class="nx">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">1</span><span class="p">],</span><span class="w"> </span><span class="nx">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">left</span><span class="p">,</span><span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">right</span><span class="p">,</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">temp</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="p">(</span><span class="nx">spfunction2</span><span class="p">[</span><span class="nx">right1</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">24</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">63</span><span class="p">]</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">spfunction4</span><span class="p">[</span><span class="nx">right1</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">63</span><span class="p">]</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">spfunction6</span><span class="p">[</span><span class="nx">right1</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">8</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">63</span><span class="p">]</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">spfunction8</span><span class="p">[</span><span class="mf">63</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="nx">right1</span><span class="p">]</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">spfunction1</span><span class="p">[</span><span class="nx">right2</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">24</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">63</span><span class="p">]</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">spfunction3</span><span class="p">[</span><span class="nx">right2</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">63</span><span class="p">]</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">spfunction5</span><span class="p">[</span><span class="nx">right2</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">8</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">63</span><span class="p">]</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">spfunction7</span><span class="p">[</span><span class="mf">63</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="nx">right2</span><span class="p">]);</span>
<span class="w"> </span><span class="nx">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">left</span><span class="p">,</span><span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">right</span><span class="p">,</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">temp</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">31</span><span class="p">,</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">1431655765</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="p">((</span><span class="nx">left</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">31</span><span class="p">)</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="nx">right</span><span class="p">),</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="p">(</span><span class="nx">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">16711935</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="p">(</span><span class="nx">right</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">8</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="p">(</span><span class="nx">left</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">temp</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">1</span><span class="p">)))</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">8</span><span class="p">,</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="p">(</span><span class="nx">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">858993459</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="p">(</span><span class="nx">right</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="p">(</span><span class="nx">left</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">temp</span><span class="p">)))</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">65535</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="p">((</span><span class="nx">left</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">temp</span><span class="p">)</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="nx">right</span><span class="p">),</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">252645135</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="p">((</span><span class="nx">left</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">temp</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">16</span><span class="p">)</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">4</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="nx">right</span><span class="p">),</span><span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">temp</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">4</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">mode</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">encrypt</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="p">(</span><span class="nx">cbcleft</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">left</span><span class="p">,</span><span class="w"> </span><span class="nx">cbcright</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">right</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">left</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">cbcleft2</span><span class="p">,</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">cbcright2</span><span class="p">)),</span><span class="w"> </span><span class="nx">tempresult</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="nb">String</span><span class="p">.</span><span class="nx">fromCharCode</span><span class="p">(</span><span class="nx">left</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">24</span><span class="p">,</span><span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">255</span><span class="p">,</span><span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">8</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">255</span><span class="p">,</span><span class="w"> </span><span class="mf">255</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="nx">left</span><span class="p">,</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">24</span><span class="p">,</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">255</span><span class="p">,</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">8</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">255</span><span class="p">,</span><span class="w"> </span><span class="mf">255</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="nx">right</span><span class="p">),</span><span class="w"> </span><span class="mf">512</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="p">(</span><span class="nx">chunk</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mf">8</span><span class="p">)</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">result</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="nx">tempresult</span><span class="p">,</span><span class="w"> </span><span class="nx">tempresult</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w"> </span><span class="nx">chunk</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">result</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="nx">tempresult</span><span class="p">,</span><span class="w"> </span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">result</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/\0*$/g</span><span class="p">,</span><span class="w"> </span><span class="s2">""</span><span class="p">),</span><span class="w"> </span><span class="o">!</span><span class="nx">encrypt</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="mf">1</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nx">padding</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">paddingChars</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span>
<span class="w"> </span><span class="p">(</span><span class="nx">len</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">result</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">paddingChars</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">result</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">len</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">)),</span><span class="w"> </span><span class="nx">paddingChars</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="mf">8</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">result</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">len</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">paddingChars</span><span class="p">))</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">decodeURIComponent</span><span class="p">(</span><span class="nx">escape</span><span class="p">(</span><span class="nx">result</span><span class="p">))</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">result</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">$</span><span class="p">.</span><span class="nx">des_createKeys</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">key</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">var</span><span class="w"> </span><span class="nx">lefttemp</span><span class="p">,</span><span class="w"> </span><span class="nx">righttemp</span><span class="p">,</span><span class="w"> </span><span class="nx">temp</span><span class="p">,</span><span class="w"> </span><span class="nx">pc2bytes0</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">4</span><span class="p">,</span><span class="w"> </span><span class="mf">536870912</span><span class="p">,</span><span class="w"> </span><span class="mf">536870916</span><span class="p">,</span><span class="w"> </span><span class="mf">65536</span><span class="p">,</span><span class="w"> </span><span class="mf">65540</span><span class="p">,</span><span class="w"> </span><span class="mf">536936448</span><span class="p">,</span><span class="w"> </span><span class="mf">536936452</span><span class="p">,</span><span class="w"> </span><span class="mf">512</span><span class="p">,</span><span class="w"> </span><span class="mf">516</span><span class="p">,</span><span class="w"> </span><span class="mf">536871424</span><span class="p">,</span><span class="w"> </span><span class="mf">536871428</span><span class="p">,</span><span class="w"> </span><span class="mf">66048</span><span class="p">,</span><span class="w"> </span><span class="mf">66052</span><span class="p">,</span><span class="w"> </span><span class="mf">536936960</span><span class="p">,</span><span class="w"> </span><span class="mf">536936964</span><span class="p">),</span><span class="w"> </span><span class="nx">pc2bytes1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">1048576</span><span class="p">,</span><span class="w"> </span><span class="mf">1048577</span><span class="p">,</span><span class="w"> </span><span class="mf">67108864</span><span class="p">,</span><span class="w"> </span><span class="mf">67108865</span><span class="p">,</span><span class="w"> </span><span class="mf">68157440</span><span class="p">,</span><span class="w"> </span><span class="mf">68157441</span><span class="p">,</span><span class="w"> </span><span class="mf">256</span><span class="p">,</span><span class="w"> </span><span class="mf">257</span><span class="p">,</span><span class="w"> </span><span class="mf">1048832</span><span class="p">,</span><span class="w"> </span><span class="mf">1048833</span><span class="p">,</span><span class="w"> </span><span class="mf">67109120</span><span class="p">,</span><span class="w"> </span><span class="mf">67109121</span><span class="p">,</span><span class="w"> </span><span class="mf">68157696</span><span class="p">,</span><span class="w"> </span><span class="mf">68157697</span><span class="p">),</span><span class="w"> </span><span class="nx">pc2bytes2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">8</span><span class="p">,</span><span class="w"> </span><span class="mf">2048</span><span class="p">,</span><span class="w"> </span><span class="mf">2056</span><span class="p">,</span><span class="w"> </span><span class="mf">16777216</span><span class="p">,</span><span class="w"> </span><span class="mf">16777224</span><span class="p">,</span><span class="w"> </span><span class="mf">16779264</span><span class="p">,</span><span class="w"> </span><span class="mf">16779272</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">8</span><span class="p">,</span><span class="w"> </span><span class="mf">2048</span><span class="p">,</span><span class="w"> </span><span class="mf">2056</span><span class="p">,</span><span class="w"> </span><span class="mf">16777216</span><span class="p">,</span><span class="w"> </span><span class="mf">16777224</span><span class="p">,</span><span class="w"> </span><span class="mf">16779264</span><span class="p">,</span><span class="w"> </span><span class="mf">16779272</span><span class="p">),</span><span class="w"> </span><span class="nx">pc2bytes3</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">2097152</span><span class="p">,</span><span class="w"> </span><span class="mf">134217728</span><span class="p">,</span><span class="w"> </span><span class="mf">136314880</span><span class="p">,</span><span class="w"> </span><span class="mf">8192</span><span class="p">,</span><span class="w"> </span><span class="mf">2105344</span><span class="p">,</span><span class="w"> </span><span class="mf">134225920</span><span class="p">,</span><span class="w"> </span><span class="mf">136323072</span><span class="p">,</span><span class="w"> </span><span class="mf">131072</span><span class="p">,</span><span class="w"> </span><span class="mf">2228224</span><span class="p">,</span><span class="w"> </span><span class="mf">134348800</span><span class="p">,</span><span class="w"> </span><span class="mf">136445952</span><span class="p">,</span><span class="w"> </span><span class="mf">139264</span><span class="p">,</span><span class="w"> </span><span class="mf">2236416</span><span class="p">,</span><span class="w"> </span><span class="mf">134356992</span><span class="p">,</span><span class="w"> </span><span class="mf">136454144</span><span class="p">),</span><span class="w"> </span><span class="nx">pc2bytes4</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">262144</span><span class="p">,</span><span class="w"> </span><span class="mf">16</span><span class="p">,</span><span class="w"> </span><span class="mf">262160</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">262144</span><span class="p">,</span><span class="w"> </span><span class="mf">16</span><span class="p">,</span><span class="w"> </span><span class="mf">262160</span><span class="p">,</span><span class="w"> </span><span class="mf">4096</span><span class="p">,</span><span class="w"> </span><span class="mf">266240</span><span class="p">,</span><span class="w"> </span><span class="mf">4112</span><span class="p">,</span><span class="w"> </span><span class="mf">266256</span><span class="p">,</span><span class="w"> </span><span class="mf">4096</span><span class="p">,</span><span class="w"> </span><span class="mf">266240</span><span class="p">,</span><span class="w"> </span><span class="mf">4112</span><span class="p">,</span><span class="w"> </span><span class="mf">266256</span><span class="p">),</span><span class="w"> </span><span class="nx">pc2bytes5</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">1024</span><span class="p">,</span><span class="w"> </span><span class="mf">32</span><span class="p">,</span><span class="w"> </span><span class="mf">1056</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">1024</span><span class="p">,</span><span class="w"> </span><span class="mf">32</span><span class="p">,</span><span class="w"> </span><span class="mf">1056</span><span class="p">,</span><span class="w"> </span><span class="mf">33554432</span><span class="p">,</span><span class="w"> </span><span class="mf">33555456</span><span class="p">,</span><span class="w"> </span><span class="mf">33554464</span><span class="p">,</span><span class="w"> </span><span class="mf">33555488</span><span class="p">,</span><span class="w"> </span><span class="mf">33554432</span><span class="p">,</span><span class="w"> </span><span class="mf">33555456</span><span class="p">,</span><span class="w"> </span><span class="mf">33554464</span><span class="p">,</span><span class="w"> </span><span class="mf">33555488</span><span class="p">),</span><span class="w"> </span><span class="nx">pc2bytes6</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">268435456</span><span class="p">,</span><span class="w"> </span><span class="mf">524288</span><span class="p">,</span><span class="w"> </span><span class="mf">268959744</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="mf">268435458</span><span class="p">,</span><span class="w"> </span><span class="mf">524290</span><span class="p">,</span><span class="w"> </span><span class="mf">268959746</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">268435456</span><span class="p">,</span><span class="w"> </span><span class="mf">524288</span><span class="p">,</span><span class="w"> </span><span class="mf">268959744</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="mf">268435458</span><span class="p">,</span><span class="w"> </span><span class="mf">524290</span><span class="p">,</span><span class="w"> </span><span class="mf">268959746</span><span class="p">),</span><span class="w"> </span><span class="nx">pc2bytes7</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">65536</span><span class="p">,</span><span class="w"> </span><span class="mf">2048</span><span class="p">,</span><span class="w"> </span><span class="mf">67584</span><span class="p">,</span><span class="w"> </span><span class="mf">536870912</span><span class="p">,</span><span class="w"> </span><span class="mf">536936448</span><span class="p">,</span><span class="w"> </span><span class="mf">536872960</span><span class="p">,</span><span class="w"> </span><span class="mf">536938496</span><span class="p">,</span><span class="w"> </span><span class="mf">131072</span><span class="p">,</span><span class="w"> </span><span class="mf">196608</span><span class="p">,</span><span class="w"> </span><span class="mf">133120</span><span class="p">,</span><span class="w"> </span><span class="mf">198656</span><span class="p">,</span><span class="w"> </span><span class="mf">537001984</span><span class="p">,</span><span class="w"> </span><span class="mf">537067520</span><span class="p">,</span><span class="w"> </span><span class="mf">537004032</span><span class="p">,</span><span class="w"> </span><span class="mf">537069568</span><span class="p">),</span><span class="w"> </span><span class="nx">pc2bytes8</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">262144</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">262144</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="mf">262146</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="mf">262146</span><span class="p">,</span><span class="w"> </span><span class="mf">33554432</span><span class="p">,</span><span class="w"> </span><span class="mf">33816576</span><span class="p">,</span><span class="w"> </span><span class="mf">33554432</span><span class="p">,</span><span class="w"> </span><span class="mf">33816576</span><span class="p">,</span><span class="w"> </span><span class="mf">33554434</span><span class="p">,</span><span class="w"> </span><span class="mf">33816578</span><span class="p">,</span><span class="w"> </span><span class="mf">33554434</span><span class="p">,</span><span class="w"> </span><span class="mf">33816578</span><span class="p">),</span><span class="w"> </span><span class="nx">pc2bytes9</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">268435456</span><span class="p">,</span><span class="w"> </span><span class="mf">8</span><span class="p">,</span><span class="w"> </span><span class="mf">268435464</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">268435456</span><span class="p">,</span><span class="w"> </span><span class="mf">8</span><span class="p">,</span><span class="w"> </span><span class="mf">268435464</span><span class="p">,</span><span class="w"> </span><span class="mf">1024</span><span class="p">,</span><span class="w"> </span><span class="mf">268436480</span><span class="p">,</span><span class="w"> </span><span class="mf">1032</span><span class="p">,</span><span class="w"> </span><span class="mf">268436488</span><span class="p">,</span><span class="w"> </span><span class="mf">1024</span><span class="p">,</span><span class="w"> </span><span class="mf">268436480</span><span class="p">,</span><span class="w"> </span><span class="mf">1032</span><span class="p">,</span><span class="w"> </span><span class="mf">268436488</span><span class="p">),</span><span class="w"> </span><span class="nx">pc2bytes10</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">32</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">32</span><span class="p">,</span><span class="w"> </span><span class="mf">1048576</span><span class="p">,</span><span class="w"> </span><span class="mf">1048608</span><span class="p">,</span><span class="w"> </span><span class="mf">1048576</span><span class="p">,</span><span class="w"> </span><span class="mf">1048608</span><span class="p">,</span><span class="w"> </span><span class="mf">8192</span><span class="p">,</span><span class="w"> </span><span class="mf">8224</span><span class="p">,</span><span class="w"> </span><span class="mf">8192</span><span class="p">,</span><span class="w"> </span><span class="mf">8224</span><span class="p">,</span><span class="w"> </span><span class="mf">1056768</span><span class="p">,</span><span class="w"> </span><span class="mf">1056800</span><span class="p">,</span><span class="w"> </span><span class="mf">1056768</span><span class="p">,</span><span class="w"> </span><span class="mf">1056800</span><span class="p">),</span><span class="w"> </span><span class="nx">pc2bytes11</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">16777216</span><span class="p">,</span><span class="w"> </span><span class="mf">512</span><span class="p">,</span><span class="w"> </span><span class="mf">16777728</span><span class="p">,</span><span class="w"> </span><span class="mf">2097152</span><span class="p">,</span><span class="w"> </span><span class="mf">18874368</span><span class="p">,</span><span class="w"> </span><span class="mf">2097664</span><span class="p">,</span><span class="w"> </span><span class="mf">18874880</span><span class="p">,</span><span class="w"> </span><span class="mf">67108864</span><span class="p">,</span><span class="w"> </span><span class="mf">83886080</span><span class="p">,</span><span class="w"> </span><span class="mf">67109376</span><span class="p">,</span><span class="w"> </span><span class="mf">83886592</span><span class="p">,</span><span class="w"> </span><span class="mf">69206016</span><span class="p">,</span><span class="w"> </span><span class="mf">85983232</span><span class="p">,</span><span class="w"> </span><span class="mf">69206528</span><span class="p">,</span><span class="w"> </span><span class="mf">85983744</span><span class="p">),</span><span class="w"> </span><span class="nx">pc2bytes12</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">4096</span><span class="p">,</span><span class="w"> </span><span class="mf">134217728</span><span class="p">,</span><span class="w"> </span><span class="mf">134221824</span><span class="p">,</span><span class="w"> </span><span class="mf">524288</span><span class="p">,</span><span class="w"> </span><span class="mf">528384</span><span class="p">,</span><span class="w"> </span><span class="mf">134742016</span><span class="p">,</span><span class="w"> </span><span class="mf">134746112</span><span class="p">,</span><span class="w"> </span><span class="mf">16</span><span class="p">,</span><span class="w"> </span><span class="mf">4112</span><span class="p">,</span><span class="w"> </span><span class="mf">134217744</span><span class="p">,</span><span class="w"> </span><span class="mf">134221840</span><span class="p">,</span><span class="w"> </span><span class="mf">524304</span><span class="p">,</span><span class="w"> </span><span class="mf">528400</span><span class="p">,</span><span class="w"> </span><span class="mf">134742032</span><span class="p">,</span><span class="w"> </span><span class="mf">134746128</span><span class="p">),</span><span class="w"> </span><span class="nx">pc2bytes13</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">4</span><span class="p">,</span><span class="w"> </span><span class="mf">256</span><span class="p">,</span><span class="w"> </span><span class="mf">260</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">4</span><span class="p">,</span><span class="w"> </span><span class="mf">256</span><span class="p">,</span><span class="w"> </span><span class="mf">260</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">5</span><span class="p">,</span><span class="w"> </span><span class="mf">257</span><span class="p">,</span><span class="w"> </span><span class="mf">261</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">5</span><span class="p">,</span><span class="w"> </span><span class="mf">257</span><span class="p">,</span><span class="w"> </span><span class="mf">261</span><span class="p">),</span><span class="w"> </span><span class="nx">iterations</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">key</span><span class="p">.</span><span class="nx">length</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mf">8</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="mf">3</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="nx">keys</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">32</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">iterations</span><span class="p">),</span><span class="w"> </span><span class="nx">shifts</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">),</span><span class="w"> </span><span class="nx">m</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="nx">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">j</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">iterations</span><span class="p">;</span><span class="w"> </span><span class="nx">j</span><span class="o">++</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">key</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">m</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">24</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">key</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">m</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">key</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">m</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">8</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">key</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">m</span><span class="o">++</span><span class="p">),</span>
<span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">key</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">m</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">24</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">key</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">m</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">key</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">m</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">8</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">key</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">m</span><span class="o">++</span><span class="p">);</span>
<span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="p">(</span><span class="nx">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">252645135</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="p">(</span><span class="nx">left</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">4</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="nx">right</span><span class="p">))</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">4</span><span class="p">,</span><span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">65535</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="p">((</span><span class="nx">right</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">temp</span><span class="p">)</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="o">-</span><span class="mf">16</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="nx">left</span><span class="p">),</span><span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="p">(</span><span class="nx">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">858993459</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="p">(</span><span class="nx">left</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="p">(</span><span class="nx">right</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">temp</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="o">-</span><span class="mf">16</span><span class="p">)))</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">65535</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="p">((</span><span class="nx">right</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">temp</span><span class="p">)</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="o">-</span><span class="mf">16</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="nx">left</span><span class="p">),</span><span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="p">(</span><span class="nx">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">1431655765</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="p">(</span><span class="nx">left</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="p">(</span><span class="nx">right</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">temp</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="o">-</span><span class="mf">16</span><span class="p">)))</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">16711935</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="p">((</span><span class="nx">right</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">temp</span><span class="p">)</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">8</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="nx">left</span><span class="p">),</span><span class="w"> </span><span class="nx">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="nx">left</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="p">(</span><span class="nx">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">1431655765</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="p">(</span><span class="nx">left</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="p">(</span><span class="nx">right</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">temp</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">8</span><span class="p">)))</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">1</span><span class="p">)</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">8</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="p">(</span><span class="nx">right</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="nx">temp</span><span class="p">)</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">20</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">240</span><span class="p">,</span><span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">24</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">8</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">16711680</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">8</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">65280</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">24</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">240</span><span class="p">,</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">temp</span><span class="p">;</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">var</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">shifts</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="nx">shifts</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="p">(</span><span class="nx">left</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">26</span><span class="p">,</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">26</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">left</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">left</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">27</span><span class="p">,</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">27</span><span class="p">),</span><span class="w"> </span><span class="nx">right</span><span class="w"> </span><span class="o">&=</span><span class="w"> </span><span class="o">-</span><span class="mf">15</span><span class="p">,</span><span class="w"> </span><span class="nx">lefttemp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">pc2bytes0</span><span class="p">[(</span><span class="nx">left</span><span class="w"> </span><span class="o">&=</span><span class="w"> </span><span class="o">-</span><span class="mf">15</span><span class="p">)</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">28</span><span class="p">]</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">pc2bytes1</span><span class="p">[</span><span class="nx">left</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">24</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">15</span><span class="p">]</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">pc2bytes2</span><span class="p">[</span><span class="nx">left</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">20</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">15</span><span class="p">]</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">pc2bytes3</span><span class="p">[</span><span class="nx">left</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">15</span><span class="p">]</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">pc2bytes4</span><span class="p">[</span><span class="nx">left</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">12</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">15</span><span class="p">]</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">pc2bytes5</span><span class="p">[</span><span class="nx">left</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">8</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">15</span><span class="p">]</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">pc2bytes6</span><span class="p">[</span><span class="nx">left</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">4</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">15</span><span class="p">],</span><span class="w"> </span><span class="nx">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">65535</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="p">((</span><span class="nx">righttemp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">pc2bytes7</span><span class="p">[</span><span class="nx">right</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">28</span><span class="p">]</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">pc2bytes8</span><span class="p">[</span><span class="nx">right</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">24</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">15</span><span class="p">]</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">pc2bytes9</span><span class="p">[</span><span class="nx">right</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">20</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">15</span><span class="p">]</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">pc2bytes10</span><span class="p">[</span><span class="nx">right</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">15</span><span class="p">]</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">pc2bytes11</span><span class="p">[</span><span class="nx">right</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">12</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">15</span><span class="p">]</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">pc2bytes12</span><span class="p">[</span><span class="nx">right</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">8</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">15</span><span class="p">]</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">pc2bytes13</span><span class="p">[</span><span class="nx">right</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">4</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mf">15</span><span class="p">])</span><span class="w"> </span><span class="o">>>></span><span class="w"> </span><span class="mf">16</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="nx">lefttemp</span><span class="p">),</span><span class="w"> </span><span class="nx">keys</span><span class="p">[</span><span class="nx">n</span><span class="o">++</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">lefttemp</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="nx">temp</span><span class="p">,</span><span class="w"> </span><span class="nx">keys</span><span class="p">[</span><span class="nx">n</span><span class="o">++</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">righttemp</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="nx">temp</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mf">16</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">keys</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">$</span><span class="p">.</span><span class="nx">genkey</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">key</span><span class="p">,</span><span class="w"> </span><span class="nx">start</span><span class="p">,</span><span class="w"> </span><span class="nx">end</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">key</span><span class="o">:</span><span class="w"> </span><span class="nx">$</span><span class="p">.</span><span class="nx">pad</span><span class="p">(</span><span class="nx">key</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="nx">start</span><span class="p">,</span><span class="w"> </span><span class="nx">end</span><span class="p">)),</span>
<span class="w"> </span><span class="nx">vector</span><span class="o">:</span><span class="w"> </span><span class="mf">1</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">$</span><span class="p">.</span><span class="nx">pad</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">key</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">var</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">key</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mf">24</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="nx">key</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="s2">"0"</span><span class="p">;</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">key</span>
<span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nx">$</span><span class="p">.</span><span class="nx">DES3</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">encrypt</span><span class="o">:</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">input</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">genKey</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">$</span><span class="p">.</span><span class="nx">genkey</span><span class="p">(</span><span class="s2">"PKCS5Padding"</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">24</span><span class="p">);</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">btoa</span><span class="p">(</span><span class="nx">$</span><span class="p">.</span><span class="nx">des</span><span class="p">(</span><span class="nx">genKey</span><span class="p">.</span><span class="nx">key</span><span class="p">,</span><span class="w"> </span><span class="nx">input</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="s2">"26951234"</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">))</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nx">decrypt</span><span class="o">:</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="p">(</span><span class="nx">input</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">genKey</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">$</span><span class="p">.</span><span class="nx">genkey</span><span class="p">(</span><span class="s2">"PKCS5Padding"</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">24</span><span class="p">);</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">$</span><span class="p">.</span><span class="nx">des</span><span class="p">(</span><span class="nx">genKey</span><span class="p">.</span><span class="nx">key</span><span class="p">,</span><span class="w"> </span><span class="nx">atob</span><span class="p">(</span><span class="nx">input</span><span class="p">),</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="s2">"26951234"</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}(</span><span class="nx">jQuery</span><span class="p">);</span>
</code></pre></div>Fixing a corrupt sqlite3 database with vbindiff2019-10-20T19:56:08+02:002019-10-20T19:56:08+02:00tomastag:www.härdin.se,2019-10-20:/blog/2019/10/20/fixing-a-corrupt-sqlite3-database-with-vbindiff/<p>A few days ago my RSS reader, <a href="https://quiterss.org/">QuiteRSS</a>, started crashing immediately on startup.
After digging around a bit in <code>~/.local/share/QuiteRss/QuiteRss</code> I discovered that a corrupted <code>feeds.db</code> file was the cause.
This file is an <a href="https://www.sqlite.org/index.html">sqlite3</a> database, which QuiteRSS uses to keep track of feeds,
which posts …</p><p>A few days ago my RSS reader, <a href="https://quiterss.org/">QuiteRSS</a>, started crashing immediately on startup.
After digging around a bit in <code>~/.local/share/QuiteRss/QuiteRss</code> I discovered that a corrupted <code>feeds.db</code> file was the cause.
This file is an <a href="https://www.sqlite.org/index.html">sqlite3</a> database, which QuiteRSS uses to keep track of feeds,
which posts the user has read, filters and so on.
Obviously, if that file is broken then I'd have to go through the process of re-adding all 182 feeds I'm currently subscribed to.
Annoying to say the least.</p>
<p>Comparing the corrupt <code>feeds.db</code> with the database from a fresh installation of QuiteRSS, using <a href="https://www.cjmweb.net/vbindiff/">vbindiff</a>, revealed the following:</p>
<pre style="background: none; border: none">
<span style="color:black;background-color:black;"></span><span style="color:gray;background-color:black;"></span><span style="color:gray;background-color:black;"></span><span style="color:white;background-color:black;"></span><span style="color:white;background-color:gray;"></span><span style="color:black;background-color:gray;">feeds-corrupt.db
</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">0000 0000: </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">01</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">01</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> 00 </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">........</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">.......</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">.
0000 0010: </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">01</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> 00 </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> 00 </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">01</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> 00 00 </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> 00 00 00 </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">.</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">.</span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">..</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">.</span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">...</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">.</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">..</span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">.</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">...</span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">.</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">
0000 0020: </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">01</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> 00 00 00 00 00 00 00 </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">01</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> 00 00 </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> 00 00 00 </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">.</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">....... </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">.</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">..</span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">.</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">...</span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">.</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">
0000 0030: </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">01</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">.</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">....... ........
0000 0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0000 0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">27</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">36</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> ........ ......</span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">'6</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">
0000 0060: 00 2E 30 3A 0D 00 00 00 0C 00 D5 00 08 B5 05 E8 ..0:.... ........
0000 0070: 05 AD 05 33 04 AB 04 0E 03 67 02 DC 02 61 01 B7 ...3.... .g...a..
0000 0080: 01 32 00 D5 00 00 00 00 00 00 00 00 00 00 00 00 .2...... ........
0000 0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0000 00A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0000 00B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0000 00C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0000 00D0: 00 00 00 00 00 5B 0C 07 17 15 15 01 81 19 74 61 .....[.. ......ta
0000 00E0: 62 6C 65 69 6E 66 6F 69 6E 66 6F 0D 43 52 45 41 bleinfoi nfo.CREA
0000 00F0: 54 45 20 54 41 42 4C 45 20 69 6E 66 6F 28 69 64 TE TABLE info(id
</span><span style="color:white;background-color:black;"></span><span style="color:white;background-color:gray;"></span><span style="color:black;background-color:gray;">feeds-fresh.db
</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">0000 0000: </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">53</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">51</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">4C</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">69</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">74</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">65</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">20</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">66</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">6F</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">72</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">6D</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">61</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">74</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">20</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">33</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> 00 </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">SQLite f</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">ormat 3</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">.
0000 0010: </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">10</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> 00 </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">01</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">01</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> 00 </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">40</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">20</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">20</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> 00 00 </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">11</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> 00 00 00 </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">0D</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">.</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">.</span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">..</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">.</span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">@ </span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">.</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">..</span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">.</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">...</span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">.</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">
0000 0020: </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> 00 00 00 00 00 00 00 </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> 00 00 </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">0E</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> 00 00 00 </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">04</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">.</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">....... </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">.</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">..</span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">.</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">...</span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">.</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">
0000 0030: </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">.</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">....... ........
0000 0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0000 0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">11</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> ........ ......</span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">..</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">
0000 0060: 00 2E 30 3A 0D 00 00 00 0C 00 D5 00 08 B5 05 E8 ..0:.... ........
0000 0070: 05 AD 05 33 04 AB 04 0E 03 67 02 DC 02 61 01 B7 ...3.... .g...a..
0000 0080: 01 32 00 D5 00 00 00 00 00 00 00 00 00 00 00 00 .2...... ........
0000 0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0000 00A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0000 00B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0000 00C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0000 00D0: 00 00 00 00 00 5B 0C 07 17 15 15 01 81 19 74 61 .....[.. ......ta
0000 00E0: 62 6C 65 69 6E 66 6F 69 6E 66 6F 0D 43 52 45 41 bleinfoi nfo.CREA
0000 00F0: 54 45 20 54 41 42 4C 45 20 69 6E 66 6F 28 69 64 TE TABLE info(id
</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">┌──────────────────────────────────────────────────────────────────────────────┐</span><span style="color:black;background-color:black;"></span><span style="color:gray;background-color:black;"></span><span style="color:gray;background-color:black;">
</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">│</span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:gray;"></span><span style="font-weight:bold;color:gray;background-color:blue;">Arrow keys</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> move </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:gray;"></span><span style="font-weight:bold;color:gray;background-color:blue;">F</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> find </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:gray;"></span><span style="font-weight:bold;color:gray;background-color:blue;">RET</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> next difference </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:gray;"></span><span style="font-weight:bold;color:gray;background-color:blue;">ESC</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> quit </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:gray;"></span><span style="font-weight:bold;color:gray;background-color:blue;">T</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> move top </span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">│</span><span style="color:black;background-color:black;"></span><span style="color:gray;background-color:black;"></span><span style="color:gray;background-color:black;">
</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">│</span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:gray;"></span><span style="font-weight:bold;color:gray;background-color:blue;">C</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="color:white;background-color:black;"></span><span style="color:white;background-color:gray;"></span><span style="color:black;background-color:gray;">ASCII</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">/EBCDIC </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:gray;"></span><span style="font-weight:bold;color:gray;background-color:blue;">E</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> edit file </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:gray;"></span><span style="font-weight:bold;color:gray;background-color:blue;">G</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> goto position </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:gray;"></span><span style="font-weight:bold;color:gray;background-color:blue;">Q</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> quit </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:gray;"></span><span style="font-weight:bold;color:gray;background-color:blue;">B</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> move bottom </span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">│</span><span style="color:black;background-color:black;"></span><span style="color:gray;background-color:black;"></span><span style="color:gray;background-color:black;">
</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">└──────────────────────────────────────────────────────────────────────────────┘</span><span style="color:black;background-color:black;"></span><span style="color:gray;background-color:black;"></span><span style="color:gray;background-color:black;"></span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"></span><span style="color:black;background-color:black;"></span><span style="color:gray;background-color:black;"></span><span style="color:gray;background-color:black;"></span>
</pre>
<p>The difference that stands out most is that the magic string "SQLite format 3" is missing from the corrupt file.
Instead the first 56 bytes of the file appear to have been replaced with seven 64-bit little-endian integers with the value 1.
Why? I have no idea. Perhaps some kind of heap corruption?</p>
<p>My first attempt at fixing this was to just replace the first 100 bytes of the file with data identical to the fresh file, which is quite easy to do with the <em>E edit file</em> command in vbindiff.
This worked well enough that I was able to open the file in <a href="https://sqlitebrowser.org/">sqlitebrowser</a> and see that the database schema and a few tables parsed OK:</p>
<p><img alt="Screenshot of sqlitebrowser" src="http://www.härdin.se/images/sqlitebrowser.png"></p>
<p>Sadly, this wasn't enough - the <code>feeds</code> table was empty.</p>
<p>After diggin around in the source code for sqlite3 for a while (mainly btreeInt.h, and lockBtree() in btree.c), I discovered that the reason for the feeds table not showing was because the nPage value in the header (bytes 28..31) was wrong.
Its value specifies the size of the file in clusters, where each cluster is 4 KiB.
So I took the size of the file (18415616 B), divided it by 4096 (4496), converted that to hexadecimal (0x1190) and put that hex value into the nPage part of the header:</p>
<pre style="background: none; border: none">
<span style="color:black;background-color:gray;">feeds-almost.db
</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">0000 0000: 53 51 4C 69 74 65 20 66 6F 72 6D 61 74 20 33 00 SQLite f ormat 3.
0000 0010: 10 00 01 01 00 40 20 20 00 00 00 11 00 00 </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">00</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">0D</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> .....@ ......</span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">..</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">
0000 0020: 00 00 00 00 00 00 00 00 00 00 00 0E 00 00 00 04 ........ ........
0000 0030: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ........ ........
0000 0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0000 0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 11 ........ ........
0000 0060: 00 2E 30 3A 0D 00 00 00 0C 00 D5 00 08 B5 05 E8 ..0:.... ........
0000 0070: 05 AD 05 33 04 AB 04 0E 03 67 02 DC 02 61 01 B7 ...3.... .g...a..
0000 0080: 01 32 00 D5 00 00 00 00 00 00 00 00 00 00 00 00 .2...... ........
0000 0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0000 00A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0000 00B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
</span><span style="color:white;background-color:black;"></span><span style="color:white;background-color:gray;"></span><span style="color:black;background-color:gray;">feeds-npage.db
</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">0000 0000: 53 51 4C 69 74 65 20 66 6F 72 6D 61 74 20 33 00 SQLite f ormat 3.
0000 0010: 10 00 01 01 00 40 20 20 00 00 00 11 00 00 </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">11</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">90</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> .....@ ......</span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:red;"></span><span style="font-weight:bold;color:red;background-color:blue;">..</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">
0000 0020: 00 00 00 00 00 00 00 00 00 00 00 0E 00 00 00 04 ........ ........
0000 0030: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ........ ........
0000 0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0000 0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 11 ........ ........
0000 0060: 00 2E 30 3A 0D 00 00 00 0C 00 D5 00 08 B5 05 E8 ..0:.... ........
0000 0070: 05 AD 05 33 04 AB 04 0E 03 67 02 DC 02 61 01 B7 ...3.... .g...a..
0000 0080: 01 32 00 D5 00 00 00 00 00 00 00 00 00 00 00 00 .2...... ........
0000 0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0000 00A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0000 00B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">┌──────────────────────────────────────────────────────────────────────────────┐</span><span style="color:black;background-color:black;"></span><span style="color:gray;background-color:black;"></span><span style="color:gray;background-color:black;">
</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">│</span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:gray;"></span><span style="font-weight:bold;color:gray;background-color:blue;">Arrow keys</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> move </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:gray;"></span><span style="font-weight:bold;color:gray;background-color:blue;">F</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> find </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:gray;"></span><span style="font-weight:bold;color:gray;background-color:blue;">RET</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> next difference </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:gray;"></span><span style="font-weight:bold;color:gray;background-color:blue;">ESC</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> quit </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:gray;"></span><span style="font-weight:bold;color:gray;background-color:blue;">T</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> move top </span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">│</span><span style="color:black;background-color:black;"></span><span style="color:gray;background-color:black;"></span><span style="color:gray;background-color:black;">
</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">│</span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:gray;"></span><span style="font-weight:bold;color:gray;background-color:blue;">C</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> </span><span style="color:white;background-color:black;"></span><span style="color:white;background-color:gray;"></span><span style="color:black;background-color:gray;">ASCII</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">/EBCDIC </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:gray;"></span><span style="font-weight:bold;color:gray;background-color:blue;">E</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> edit file </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:gray;"></span><span style="font-weight:bold;color:gray;background-color:blue;">G</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> goto position </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:gray;"></span><span style="font-weight:bold;color:gray;background-color:blue;">Q</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> quit </span><span style="font-weight:bold;"></span><span style="font-weight:bold;color:gray;"></span><span style="font-weight:bold;color:gray;background-color:blue;">B</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"> move bottom </span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">│</span><span style="color:black;background-color:black;"></span><span style="color:gray;background-color:black;"></span><span style="color:gray;background-color:black;">
</span><span style="color:gray;"></span><span style="color:gray;background-color:blue;">└──────────────────────────────────────────────────────────────────────────────┘</span><span style="color:black;background-color:black;"></span><span style="color:gray;background-color:black;"></span><span style="color:gray;background-color:black;"></span><span style="color:gray;"></span><span style="color:gray;background-color:blue;"></span><span style="color:black;background-color:black;"></span><span style="color:gray;background-color:black;"></span>
</pre>
<p>And the result?</p>
<p><img alt="QuiteRSS working" src="http://www.härdin.se/images/quiterss-working.png"></p>
<p>It worked! 🕺</p>
<p>At this point I exported all my feeds as an <a href="https://en.wikipedia.org/wiki/OPML">OPML</a> file,
to have it a friendlier, interchangable XML form.
The lesson from all this? I need to improve my backup system..
But on the plus side I learned quite a bit about sqlite3's internals!</p>Lifan E3 teardown2019-08-04T22:53:16+02:002019-08-04T22:53:16+02:00tomastag:www.härdin.se,2019-08-04:/blog/2019/08/04/lifan-e3-teardown/<p>This post details my findings tearing down the Lifan E3 electric moped I bought about a month ago.
I have some modifications in mind for it, and I reasoned my findings might be useful to someone else who comes across this post.</p>
<p>My Lifan E3 is configured as a class …</p><p>This post details my findings tearing down the Lifan E3 electric moped I bought about a month ago.
I have some modifications in mind for it, and I reasoned my findings might be useful to someone else who comes across this post.</p>
<p>My Lifan E3 is configured as a class 2 moped under EU law.
This means a top speed of 25 km/h and 1 kW nominal motor power ("märkeffekt").
It also means it's legal to drive wherever bikes are allowed, unlike class 1 mopeds.
It is sold under the brand "Viverra".</p>
<p>This post have been updated a few times for new information.
See the end of this post for details about what updates have been made.</p>
<p>On to the teardown itself.
In the words of Dave Jones: don't turn it on, take it apart!</p>
<h2>Tools</h2>
<p>Here is a selection of tools useful for disassembly:</p>
<ul>
<li>A set of Phillips head (PH) screwdrivers</li>
<li>A set of flat head screwdrivers</li>
<li>4 mm hex key (hardened, not the soft junk that comes with the moped)</li>
<li>5 mm hex key</li>
<li>8 mm combination spanner</li>
<li>10 mm spanner (any type)</li>
<li>15 mm spanner (any type)</li>
<li>16 mm spanner (any type)</li>
<li>24 mm hex socket</li>
</ul>
<p>You can get away with adjustable spanners for 10-16 mm.
The 8 mm combination spanner is necessary to remove the ESC.
The 24 mm hex socket is necessary to remove the rear wheel.</p>
<h2>Fasteners and general construction</h2>
<p>Most of the fasteners are PH screws, with some hex screws thrown in.
I quickly found out the provided hex key is made from Chinesium,
which got rounded off from trying to loosen some particularly well-torqued screws.
An IKEA hex key works better.</p>
<p>There are also some hex head screws of various sizes.
Some of these are hard to get at.
Use a suitable socket wrench.</p>
<p>There's a bajillion screws holding everything together,
and some of the panels slide into eachother.
This makes removing say the rider treadle incredibly tedious.</p>
<h2>Rust</h2>
<p>There is already some surface rust visible on some of the larger hex head fasteners.
Perhaps they are made from the same grade of steel as the hex key?
For now I have cold galvanized them by spraying them with zink spray.</p>
<h2>Rear</h2>
<p>There's three main things going on at the rear of the vehicle:
lights, suspension and the motor/rear wheel.</p>
<h3>Lights</h3>
<p>Nothing special, just a bunch of high-power LEDs.</p>
<h3>Suspension</h3>
<p>The rear is suspended by a combination of a pair of progressive springs and hydropneumatic damper/spring devices.
They are not adjustable, despite what the manual claims.</p>
<h3>Rear wheel / motor</h3>
<p>The motor is a 10ZW6065317 hub motor from Bosch, with a nominal voltage of 60V.
It has eight wires coming off it: three for the windings, two for sensor power and three for Hall effect sensor signals.
This is in line with the schematic.</p>
<p>To remove the rear wheel you'll need a 24 mm socket and an 8 mm open or combination spanner.
You'll also need to disconnect the windings and Hall sensor connector from the ESC, see the ESC section.</p>
<p>First loosen the 24 mm hex nuts.
You may need to hold the frame while applying torque on each nut.
Just kinda manhandle them into submission.
Remove the nuts and lock washers, then remove the 8 mm hex screws and the slotted plates.
Note the orientation of the circular locating plates on the inside on either side of the fork.
The rear wheel can now be pulled off.</p>
<h2>Middle</h2>
<p><a href="http://www.härdin.se/images/Lifan-inside.jpg"><img alt="Middle without battery compartment, annotated" src="http://www.härdin.se/images/tLifan-inside.jpg"></a></p>
<p>The middle part contains many things, all of which are under the seat.
Accessing these involves removing the battery compartment (six hex screws) and the panel holding the charge port (three PH screws).</p>
<p>The right side has the DC/DC converter, blinker relay and fuses.
The front part has the electronic speed controller (ESC) and the charging port.
The rear part has the automatic circuit breaker.</p>
<h3>Electronic speed controller</h3>
<p>The ESC is located under the seat, in front of the battery compartment.
It is marked:</p>
<div class="highlight"><pre><span></span><code><span class="n">ZWK060035</span><span class="w"> </span><span class="mi">1200</span><span class="n">W</span><span class="w"> </span><span class="n">EMark</span><span class="w"> </span><span class="mi">25</span><span class="p">[</span><span class="n">chinese</span><span class="w"> </span><span class="n">character</span><span class="p">]</span>
<span class="n">S</span><span class="o">/</span><span class="n">N</span><span class="o">:</span><span class="w"> </span><span class="mi">60</span><span class="n">V</span><span class="w"> </span><span class="p">[</span><span class="n">serial</span><span class="w"> </span><span class="n">number</span><span class="p">]</span>
<span class="n">Wuxi</span><span class="w"> </span><span class="n">Lingbo</span><span class="o">-</span><span class="n">elec</span><span class="w"> </span><span class="n">Electronic</span><span class="w"> </span><span class="n">Technologies</span><span class="w"> </span><span class="n">Co</span><span class="w"> </span><span class="n">Ltd</span>
</code></pre></div>
<p>The ESC has the following things connected:</p>
<ul>
<li>battery power (red and black)</li>
<li>motor windings (blue, green and yellow)</li>
<li>motor Hall effect sensors (small latching connector)</li>
<li>cable for display, lights, accelerator, USB and so on (large connector)</li>
</ul>
<p>The ESC will refuse to turn the rear wheel if the Hall effect sensors are disconnected.
The speed of the rear wheel will be reported on the display even if the motor windings are disconnected.
The ESC will turn the rear wheel even if the display is disconnected.</p>
<p>Both the ESC and the motor are more capable than required for class 2.
Power and max speed are limited by software in the ESC.</p>
<p>Let's move on to removal and disassembly.</p>
<p><a href="http://www.härdin.se/images/lifan/PB112022.JPG"><img alt="ESC, freshly removed" src="http://www.härdin.se/images/lifan/tPB112022.JPG"></a></p>
<p>To proceed you'll need a set of PH and flat head screwdrivers and an 8 mm combination or ring spanner.
Use the ring end of the spanner to loosen the hex screws. There is not enough room to use an open spanner.</p>
<p>To disassemble, remove the five PH screws holding the ESC together, one on the front and four on the back.
Use some flat head screwdrivers to pry the plastic case off the heatsink.
The colored rings that the screw terminals jut out of are rubber seals which are what's resisting the prying.</p>
<p>Once the case is removed, the guts of the unit are revealed:</p>
<p><a href="http://www.härdin.se/images/lifan/PB112023.JPG"><img alt="ESC opened, revealing its PCB" src="http://www.härdin.se/images/lifan/tPB112023.JPG" style="max-width:49%"></a> <a href="http://www.härdin.se/images/lifan/PB112033.JPG"><img alt="Another shot from the top" src="http://www.härdin.se/images/lifan/tPB112033.JPG" style="max-width:49%"></a> <a href="http://www.härdin.se/images/lifan/PB112026.JPG"><img alt="ESC PCB viewed from the south" src="http://www.härdin.se/images/lifan/tPB112026.JPG" style="max-width:49%"></a> <a href="http://www.härdin.se/images/lifan/PB112025.JPG"><img alt="ESC PCB viewed from the north" src="http://www.härdin.se/images/lifan/tPB112025.JPG" style="max-width:49%"></a></p>
<p>The bottom left has some informative markings:</p>
<p><a href="http://www.härdin.se/images/lifan/PB112030.JPG"><img alt="Board revision and CAN transceiver" src="http://www.härdin.se/images/lifan/tPB112030.JPG"></a></p>
<blockquote>
<p>LBMCHK3Con1.5</p>
<p>2016-12-23</p>
<p><a href="http://www.lingbo-mc.com/">www.lingbo-mc.com</a></p>
</blockquote>
<p><a href="http://www.härdin.se/images/lifan/PB112028.JPG"><img alt="STM32F closeup, and surrounding components" src="http://www.härdin.se/images/lifan/tPB112028.JPG"></a></p>
<p>There is an STM32F microcontroller in the middle of the board with these markings:</p>
<div class="highlight"><pre><span></span><code>STM32F
302C8T6
GQ2AH 179U
CHN GQ 750
</code></pre></div>
<p>The STM is clocked by an SMD crystal marked "TXC 8.00 MFLE".</p>
<p>There are some 0 Ohm resistors and unpopulated footprints around the STM, possibly for configuration.
There is a <a href="https://www.nxp.com/docs/en/data-sheet/TJA1057.pdf">TJA1057 CAN transceiver</a> in the lower left of the board.
This is likely used to talk to the speedometer/display.
There is an SO8 in the lower right marked</p>
<div class="highlight"><pre><span></span><code>U3012
S1717
</code></pre></div>
<p>This is likely a buck converter. There is a "+15V" label nearby.
There is a nearby SOT-223 marked:</p>
<div class="highlight"><pre><span></span><code><span class="mf">1117</span><span class="w"> </span><span class="mf">8</span>
<span class="mf">33</span><span class="w"> </span><span class="n">OF7J</span>
</code></pre></div>
<p>likely a fixed 3.3V <a href="http://www.ti.com/lit/ds/symlink/lm1117.pdf">LM1117</a> clone.
The 1117 is fed +5V.</p>
<p>Between the STM and the regulator section there is an SO8 marked</p>
<div class="highlight"><pre><span></span><code><span class="n">C32</span>
<span class="o">[</span><span class="n">logo</span><span class="o">]</span>
<span class="n">F90Y</span>
</code></pre></div>
<p>The logo looks like "LI" stylized.
A test point marked TRAP_P sits nearby.
There is a second C32 just north of the STM.
Both C32's have two diodes around them, some resistors and some capacitors.</p>
<p>There is space for two debug headers to the west of the STM, one 4-pin and one 3-pin.
The 4-pin one's pins are marked "3.3V", "SWCLK", "GND" and "SWDIO". A synchronous bus of some kind, maybe I2C or something for programming the STM.
The 3-pin one's pins are marked "GND", "TXD" and "RXD". Likely a 3.3V UART.
Neither of the headers are connected to the CAN transceiver.</p>
<p>There are three MOSFET drivers marked</p>
<div class="highlight"><pre><span></span><code>FORTIOR
FD2203S
EJ2007
</code></pre></div>
<p>Each of them likely drives four of the MOSFETs each.
Here is a datasheet: <a href="https://lcsc.com/product-detail/MOS-Drivers_FD2203_C97684.html">link</a></p>
<p>The four big capacitors are 470 µF 100 V, branded <a href="http://www.slf-capacitor.com/">SLF</a>, from their HE line, which features "Long life, high Ripple Current, Ultra low ESR".</p>
<p>In the upper right there are three links. Nearby are the labels "RSA", "RSB" and "RSC".
This likely means that the three links are shunt resistors for sensing the current going through each motor winding.
I don't have the equipment necessary to measure their resistances.</p>
<p>There is a horizontal row of screw terminals in the middle of the board, marked "VB+", "A", "B", "C" and "GND".
Along the north of the board there are two copper bars, going from VB+ and GND respectively, about 2/3rds of the board in either direction.
Finally, there are twelve MOSFETs along the top of the board.</p>
<p>Summary of visible test points:</p>
<ul>
<li>Uat, Uab, Ubt, Ubb, Uct, Ucb (top, near MOSFETs)</li>
<li>RSA, RSB, RSB (top right)</li>
<li>Unlabeled (bottom left, near CAN transceiver)</li>
<li>TRAP_P, +3.3V, +5V, CD2, +15V (bottom right)</li>
</ul>
<h3>Hall effect sensor port</h3>
<p>The Hall effect sensors port has three pins, of which five are used.
The following schematic shows the pin assignments I've been able to deduce so far:</p>
<p><img alt="Hall effect sensor port" src="http://www.härdin.se/images/lifan-hall.png"></p>
<p>This image is looking at the port, not the plug.
Pins 1-3 match the orientation of J2 on the PCB.
Pins 4-6 are not marked, so I'm picking the same right-left order for them.
In other words pins are counted right-left, top-bottom.
Pin 2 is unused and lacks a socket on the plug side.
Pins 1, 5 and 6 are polarized so the plug cannot be inserted the wrong way.
The following table details my understanding of each pin's function as of 2019-11-11:</p>
<table>
<tr>
<th>Pin</th>
<th>Name</th>
<th>Function</th>
</tr>
<tr>
<td>1</td>
<td>+5V</td>
<td>5 Volt supply. Logic seems to be 3.3V however, so be careful</td>
</tr>
<tr>
<td>2</td>
<td></td>
<td>Not connected</td>
</tr>
<tr>
<td>3</td>
<td>GND</td>
<td>Ground</td>
</tr>
<tr>
<td>4</td>
<td>S3</td>
<td>Third signal. Varies between 0...200 mV</td>
</tr>
<tr>
<td>5</td>
<td>S2</td>
<td>Second signal. Varies between 0...400 mV</td>
</tr>
<tr>
<td>6</td>
<td>S1</td>
<td>First signal. Varies between -100...0 mV</td>
</tr>
</table>
<p>I may have messed up the measurement on S1, hence why it is negative.
I'd need some kind of jig to scope these signals out properly.
S1...S3 measure 3.3V on the socket side, likely due to pull-up resistors.
It is possible pull-ups are required to get proper signals.</p>
<p>The cables going to the plug have five colors:
black, red, yellow, green and blue.
Black and red are likely GND and +5V while the remaining cables are likely the signals.
The colors of the signal cables would then match the colors on the wires going to the motor windings.</p>
<p>The period of the signals is somewhere around 10°.
Certainly more than a few cycles per revolution.</p>
<h3>Charging port</h3>
<p>The charging port in front of the seat uses the same 5-pin jack connector as the battery.
Only three pins are actually used: positive, negative and the middle "G" pin (purple wire).
This corresponds well to the <a href="https://a0.sofastcdn.com/attachment/ilijKBjiioSRkiopmlijSR7ww7fgzb73m/60V-Final-.pdf">FCC photographs of the innards of the charger</a>,
which show that the charger's cable only has three wires.
The schematic given in the manual only shows the power pins being connected, not the G pin.
There is continuity between the G pin and a purple wire going to a pin on the main ESC connector.
There is no continuity between the G pin on the charge port and the corresponding pin on the battery connector.
So what is the G pin for?</p>
<p><img alt="It is a mystery" src="http://www.härdin.se/images/iiam.gif"></p>
<p>My best guess is that it's for a temperature sensor in the battery.</p>
<h3>Battery connector</h3>
<p>The battery connector uses the plug equivalent of the 5-pin connector on the charge port/battery.
There is continuity from all pins on the plug to the positive connector on the charge port
in the forward direction (black probe in jack, red probe on plug pins), but not in the reverse direction (red in jack, black on plug).
Not much help for figuring out the G pin.</p>
<h3>DC/DC converter</h3>
<p>A DC/DC converter is used to produce 12V from 60V.
It is held in place with two 10 mm hex nuts.
It has four wires connected to it, which is one more than the schematic claims.</p>
<p><s>
Two wires (black and red/black) have continuity between eachother and battery negative (B in schematic).
The white/red wire seems to be battery positive (RW in schematic).
The red wire would then be the +12V output, but it is marked as RB in schematic for some reason.
The flasher has a red/black, a black and a gray wire going into it, which would contradict that.
So a minor mystery here, but nothing a little bench experimentation can't sort out once the converter has been removed.
</s></p>
<p>2020-04-14 update: There is actually not a dead short between black and red-black, it measures 3.2 ohms.
Red-white measures 0.3 ohms to battery positive when ignition and the automatic fuse are "on".</p>
<p>The converter's housing has two sets of markings.
One set is in Chinese which I cannot read, the other is the following:</p>
<div class="highlight"><pre><span></span><code><span class="mf">60</span><span class="n">V</span><span class="o">-</span><span class="mf">12</span><span class="n">V</span>
<span class="n">LF</span><span class="w"> </span><span class="mf">1200</span><span class="n">DT</span>
<span class="mf">20180309</span>
</code></pre></div>
<p>The connector is marked ZH15-31SH. Pin 1 is marked inside the housing.
Based on the above I have come up with this hypothetical pinout (pins are counted left-right top-bottom):</p>
<table>
<tr><th>Pin</th><th>Wire color</th><th>Voltage when on</th><th>Function</th></tr>
<tr><td>1</td><td>Red-black (RB)</td><td>12V</td><td>12V out</td></tr>
<tr><td>2</td><td>Red-white (RW)</td><td>60V</td><td>60V in</td></tr>
<tr><td>3</td><td>Black (B)</td><td>0V</td><td>GND</td></tr>
<tr><td>4</td><td>Red (R)</td><td>60V</td><td>Control</td></tr>
</table>
<p>That the control signal is 60V is surprising.
It has continuity with the red wire on the ESC connectors.</p>
<p>Measuring them with a multimeter in diode mode give the following voltage drops:</p>
<p>244 mV from pin 3 to pin 1<br/>
328 mV from pin 1 to pin 3<br/>
631 mV from pin 1 to pin 4<br/>
897 mV from pin 3 to pin 4<br/></p>
<p>"From" means red probe and "to" means black probe.</p>
<p>I do not yet know the maximum current that the converter can output.
Based on its size I'd say somewhere between 5-10A.</p>
<h3>Flasher</h3>
<p>The flasher has three wires: black, red/black and gray.
Black has continuity with red/black, both on the flasher and on the DC/DC connector.
There is only two wires in the schematic (RB and Gr).</p>
<h3>Fuses</h3>
<p>The fuses have two wires, both red.</p>
<h2>Front</h2>
<p>The front has these things going on:
ignition key, USB power outlet, controls, lights and the front wheel.</p>
<h3>Ignition key</h3>
<p>The ignition key has some wires sticking out of it, likely going into the ESC.
It also has a Bowden cable going to the lock under the seat.</p>
<h3>USB power outlet</h3>
<p>There is a USB jack in the bottle/phone holder, which I hadn't noticed before performing this teardown.
This implies presence of a +5V bus, which the schematic also claims.</p>
<h3>Accelerator</h3>
<p>The accelerator handle is connected by Bowden cable to a box containing a Hall effect sensor.
The sensor is marked:</p>
<div class="highlight"><pre><span></span><code><span class="mf">49</span><span class="n">E</span>
<span class="mf">754</span><span class="n">BG</span>
</code></pre></div>
<p>Judging by the internets, this is a common 49E sensor with the following pinout: 1=Vcc, 2=GND, 3=Analog out.
Cable colors supports this.
Vcc should be in the range 3 to 6.5 V.</p>
<p>Twisting the handle turns a plastic piece in the box, with a metal strip mounted to it.
This metal strip is likely progressively magnetized.</p>
<h3>Lights</h3>
<p>Nothing fancy, just LEDs.</p>
<h3>Front wheel</h3>
<p>The front wheel is held in place with a 220 mm long threaded bolt with a 15 mm hex head.
The threaded end is fastened with a 16 mm hex nut.
You'll need to use two spanners, adjustable or fixed, one on either end, to loosen the bolt.
There are two collars on the shaft used for locating, be careful not to lose them.</p>
<p>The brake disk is marked "3mm" "LYZ" and "MINTH.".</p>
<h2>Closing remarks</h2>
<p>Putting everything back together was surprisingly easy.
I have not yet figured out how to remove the rider treadle.
There are some loose connectors under it which I'd like to investigate.</p>
<p>If you have more information about Lifan's electric scooters,
feel free to contact me!</p>
<h2>Updates</h2>
<h3>2020-04-14</h3>
<p>Added more information about the DC/DC-converter.</p>
<h3>2019-11-12</h3>
<p>Added more pictures.</p>
<h3>2019-11-11</h3>
<p>Added information about hex sizes on front and rear wheels,
a list of tools,
information on how to remove the ESC,
and a rough look at the layout, component choices and features on the ESC.</p>
<p>The Hall effect sensor section was mirrored, to correspond better to the pin assignments on J2 on the PCB.</p>
<h3>2019-09-12</h3>
<p>Added information about the Hall effect sensor port.</p>HTTPS problem fixed2019-07-19T15:31:34+02:002019-07-19T15:31:34+02:00tomastag:www.härdin.se,2019-07-19:/blog/2019/07/19/https-problem-fixed/<p>Due to a misconfiguration of apache2,
the vhost for xynphzf7j7newda6.onion was intercepting requests on port 443.
This affected this site, fmigo.net and scube.se.
The problem has been fixed, and everything seems to be working OK now.</p>Demoscene category added2019-05-19T23:22:02+02:002019-05-19T23:22:02+02:00tomastag:www.härdin.se,2019-05-19:/blog/2019/05/19/demoscene-category-added/<p>I spent some time today figuring out what demoscene productions I've been involved with over the years.
The result is that a <a href="../../../../../category/demoscene.html">demoscene category</a> has been added to this site.
Check it out!
This category also becomes part of the main RSS/Atom feed of this site, which is convenient …</p><p>I spent some time today figuring out what demoscene productions I've been involved with over the years.
The result is that a <a href="../../../../../category/demoscene.html">demoscene category</a> has been added to this site.
Check it out!
This category also becomes part of the main RSS/Atom feed of this site, which is convenient since it saves on having to write two posts whenever I publish a new prod.
Woo!</p>Härdin.se - now also over HTTPS!2019-03-17T21:06:46+01:002019-03-17T21:06:46+01:00tomastag:www.härdin.se,2019-03-17:/blog/2019/03/17/haerdin-se-now-also-over-https/<p>This site is now available over HTTPS, via <a href="https://letsencrypt.org/">Let's Encrypt</a>.
Thanks to <a href="https://certbot.eff.org/">certbot</a>, getting this up and running was easier than I thought it would be.</p>
<p>There were two hurdles in the getting-on-HTTPS process:
first the blackhole stuff in my Apache config prevented port 443 from speaking TLS.
I've removed …</p><p>This site is now available over HTTPS, via <a href="https://letsencrypt.org/">Let's Encrypt</a>.
Thanks to <a href="https://certbot.eff.org/">certbot</a>, getting this up and running was easier than I thought it would be.</p>
<p>There were two hurdles in the getting-on-HTTPS process:
first the blackhole stuff in my Apache config prevented port 443 from speaking TLS.
I've removed *:443 from that VirtualHost entry for the time being, which fixed that problem.
The second problem was getting the redirects from härdin.se, haerdin.se and www.haerdin.se to www.härdin.se working.
This just involved copying and pasting another bunch of VirtualHost entries,
since I haven't figured out how to do wildcard certs yet, or if they even help in this case.</p>
<p>I also went and did the same things to fmigo.net, which is now also available at <a href="https://www.fmigo.net/">https://www.fmigo.net/</a>.</p>
<p>A few problems remain.
For example, the RSS and Atom feeds still point to the HTTP version of the site.
Ideally I'd like to provide feeds with links that use the appropriate protocol on both sites (http:// links over HTTP, https:// links over HTTPS),
but that is quite a bit of work.
So for now the links to the feeds and inside them are always HTTP,
even if it's possible to grab them over HTTPS.</p>
<p>Finally, I also set up a <a href="https://www.prosody.im/">prosody</a> server for XMPP,
which uses the same cert as haerdin.se.</p>Make sure your website works over Tor, dammit2019-01-06T20:49:35+01:002019-01-06T20:49:35+01:00tomastag:www.härdin.se,2019-01-06:/blog/2019/01/06/make-sure-your-website-works-over-tor-dammit/<p>This image macro showed up on my GNU social feed today, and it summarizes my feelings about Cloudflare over the last year or two:</p>
<p><img style="border:1px solid #000" alt="Dear Tor user, we need to make sure you are a human. To keep our customers websites secure, we didn't find a better solution than blocking you by getting you stuck in an endless loop of unsolvable captchas. Oh, and of course, we don't give a shit about your need for privacy and anonymity." src="http://www.härdin.se/images/869fab8fcc6171610fb4c073b0c078dedfeb8ff64868016877cf6288accd3675.jpg"/></p>
<p>The problem here is that a lot of clueless Web developers become customers of Cloudflare in order to handle distributing their bloated Web stuff,
and Cloudflare …</p><p>This image macro showed up on my GNU social feed today, and it summarizes my feelings about Cloudflare over the last year or two:</p>
<p><img style="border:1px solid #000" alt="Dear Tor user, we need to make sure you are a human. To keep our customers websites secure, we didn't find a better solution than blocking you by getting you stuck in an endless loop of unsolvable captchas. Oh, and of course, we don't give a shit about your need for privacy and anonymity." src="http://www.härdin.se/images/869fab8fcc6171610fb4c073b0c078dedfeb8ff64868016877cf6288accd3675.jpg"/></p>
<p>The problem here is that a lot of clueless Web developers become customers of Cloudflare in order to handle distributing their bloated Web stuff,
and Cloudflare "helpfully" provides anti-spam and anti-scraping tools.
These tools are provided partly via fingerprinting and partly via incredibly annoying <a href="https://en.wikipedia.org/wiki/CAPTCHA">CAPTCHAs</a>,
which a user must fill out even if they're only <em>browsing</em> a website.
This also breaks all kinds of automation on the Web for anyone who isn't Google, Microsoft, Cloudflare or any other Cloudflare-approved actor.
One example would be those running <a href="https://en.wikipedia.org/wiki/YaCy">YaCy</a> or any other Web archiving/indexing tool.</p>
<p>Another problem with Cloudflare is that they have the position of being the middle-man for a lot of Web traffic, often without Web users being able to tell.
This is a huge privacy problem, especially for activists.
They also knowingly help various authoritarian groups, for crass profitarian reasons.
But, griping about SV companies failing to meet basic standards of decency is a post for another time..</p>
<p>So, I ask the following of you dear reader:
if you are deploying a Web thing, do your best to avoid using Cloudflare.
If you find that you can't handle the traffic on your own machines or on a modest VPS setup,
consider slimming your site down - this page makes do with 114 KiB or so, and it has a big 'ol meme on it. You can do better!
Finally, if you must use Cloudflare anyway then make sure your site works with <a href="https://www.torproject.org/download/download-easy.html.en">Tor browser</a> at the highest security level.</p>
<p>If after reading this you find a way to be friendlier to those of us who value privacy, then I and many like me will be very grateful!</p>Trying out Frama-C2018-11-20T20:03:41+01:002018-11-20T20:03:41+01:00tomastag:www.härdin.se,2018-11-20:/blog/2018/11/20/trying-out-frama-c/<p>This is a bit of a follow-up to <a href="http://www.härdin.se/blog/2018/01/20/trying-out-ada-spark/">the previous post about Ada SPARK</a>.
In it I mentioned that SPARK has some limitations, that every program must terminate and it can't perform dynamic memory allocation (<em>update: this is not quite accurate, see the <a href="http://www.härdin.se/blog/2018/01/20/trying-out-ada-spark/#comments">comments section in the Ada SPARK post …</a></em></p><p>This is a bit of a follow-up to <a href="http://www.härdin.se/blog/2018/01/20/trying-out-ada-spark/">the previous post about Ada SPARK</a>.
In it I mentioned that SPARK has some limitations, that every program must terminate and it can't perform dynamic memory allocation (<em>update: this is not quite accurate, see the <a href="http://www.härdin.se/blog/2018/01/20/trying-out-ada-spark/#comments">comments section in the Ada SPARK post</a></em>).
A few months after writing about SPARK I came across <a href="https://frama-c.com/">Frama-C</a>,
which is a tool for doing formal verification of C code using the
<a href="https://frama-c.com/acsl.html">ANSI/ISO C Specification Language (ACSL)</a>.
With ACSL you can add contracts to C functions, and Frama-C can use some of its plugins to verify that said contracts are fulfilled.
This is nice since C is more powerful than SPARK, and having contracts in C fixes one of its most glaring flaws:
programs tending to crash, often and spectacularly.</p>
<p>In order to provide a fair comparison with Ada SPARK,
I have decided to implement the same integer square root functions in ACSL.
Let's start with the function that uses a for loop to compute the correct value:</p>
<div class="highlight"><pre><span></span><code><span class="cm">/*@ requires 0 <= num <= INT_MAX;</span>
<span class="cm"> ensures 0 <= \result <= 46340; //WP doesn't need this, but it's nice for users to know</span>
<span class="cm"> ensures \result*\result <= num < (\result+1)*(\result+1);</span>
<span class="cm"> assigns \nothing;</span>
<span class="cm"> */</span>
<span class="kt">int</span><span class="w"> </span><span class="nf">isqrt</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">num</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">num</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">2</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">num</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="cm">/*@ loop assigns i;</span>
<span class="cm"> loop invariant i*i <= num;</span>
<span class="cm"> loop variant 46340-i;</span>
<span class="cm"> */</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">46340</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">num</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">i</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">46340</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>We can see that ACSL annotations start with /*@ (or //@).
For this function we have some requirements, some statements on what the function ensures for the result,
and an assigns clause.
The assigns clause is something we didn't see in Ada SPARK.
It is used to say whether the function has any side effects.
This function doesn't, so we tell <code>frama-c</code> that it assigns \nothing.</p>
<p>The rest of the function is similar to the SPARK example,
except we have to deal with some off-by-one issues due to differences in how C and Ada loops work.
The loop has an assigns clause, just like the function.
A loop invariant allows the Weakest Predicate (WP) plugin to reason about the behavior of <code>i</code>,
and the variant clause lets WP know that the loop terminates, and how it terminates.
For simple loops it can often be omitted.</p>
<p>Next up is the recursive version, <code>isqrt2</code>:</p>
<div class="highlight"><pre><span></span><code><span class="cm">/*@ requires 1 <= lo < hi <= 46340;</span>
<span class="cm"> requires lo*lo <= num < hi*hi;</span>
<span class="cm"> ensures lo <= \result < hi;</span>
<span class="cm"> ensures \result*\result <= num < (\result+1)*(\result+1);</span>
<span class="cm"> assigns \nothing;</span>
<span class="cm"> */</span>
<span class="kt">int</span><span class="w"> </span><span class="nf">isqrt2_inner</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">num</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">lo</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">hi</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">lo</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">hi</span><span class="mi">-1</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">lo</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">mid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">lo</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">hi</span><span class="p">)</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mi">2</span><span class="p">;</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">mid</span><span class="o">*</span><span class="n">mid</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="n">num</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">isqrt2_inner</span><span class="p">(</span><span class="n">num</span><span class="p">,</span><span class="w"> </span><span class="n">lo</span><span class="p">,</span><span class="w"> </span><span class="n">mid</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">isqrt2_inner</span><span class="p">(</span><span class="n">num</span><span class="p">,</span><span class="w"> </span><span class="n">mid</span><span class="p">,</span><span class="w"> </span><span class="n">hi</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
<span class="cm">/*@ requires 0 <= num <= INT_MAX;</span>
<span class="cm"> ensures 0 <= \result <= 46340;</span>
<span class="cm"> ensures \result*\result <= num < (\result+1)*(\result+1);</span>
<span class="cm"> assigns \nothing;</span>
<span class="cm"> */</span>
<span class="kt">int</span><span class="w"> </span><span class="nf">isqrt2</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">num</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">num</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">2</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">num</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">num</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="mi">46340</span><span class="o">*</span><span class="mi">46340</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">46340</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">isqrt2_inner</span><span class="p">(</span><span class="n">num</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">46340</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div>
<p>Again we see the similarities with SPARK.
There are no annotations inside the functions,
suggesting WP is better able to reason about the code than <code>gnatprove</code>.</p>
<p>Now that we have some code, we'll want to verify it.
For many tasks, just using the WP plugin is enough.
It is invoked via <code>-wp</code>, and options to it are given via <code>-wp-optionname</code>.
Help is provided with <code>-wp-h</code>.
To invoke WP via Frama-C on our example isqrt implementations, we do: <code>frama-c -wp -wp-rte isqrt.c</code>.
The <code>-wp-rte</code> option suppresses "[wp] Warning: Missing RTE guards",
and is typically a good idea to include.
To quote <a href="https://frama-c.com/download/frama-c-wp-tutorial.pdf">the Frama-C WP tutorial</a>:</p>
<blockquote>
<p>[The RTE] plug-in generates assertions in the program wherever a runtime error might occur.
Then, the WP plug-in can try to discharge the generated assertions.</p>
</blockquote>
<p>For the full program listed in the appendix, the output of <code>frama-c</code> (version Chlorine-20180502) is this:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>frama-c<span class="w"> </span>-wp<span class="w"> </span>-wp-rte<span class="w"> </span>isqrt.c<span class="w"> </span>
<span class="o">[</span>kernel<span class="o">]</span><span class="w"> </span>Parsing<span class="w"> </span>isqrt.c<span class="w"> </span><span class="o">(</span>with<span class="w"> </span>preprocessing<span class="o">)</span>
<span class="o">[</span>rte<span class="o">]</span><span class="w"> </span>annotating<span class="w"> </span><span class="k">function</span><span class="w"> </span>isqrt
<span class="o">[</span>rte<span class="o">]</span><span class="w"> </span>annotating<span class="w"> </span><span class="k">function</span><span class="w"> </span>isqrt2
<span class="o">[</span>rte<span class="o">]</span><span class="w"> </span>annotating<span class="w"> </span><span class="k">function</span><span class="w"> </span>isqrt2_inner
<span class="o">[</span>rte<span class="o">]</span><span class="w"> </span>annotating<span class="w"> </span><span class="k">function</span><span class="w"> </span>main
<span class="o">[</span>wp<span class="o">]</span><span class="w"> </span><span class="m">89</span><span class="w"> </span>goals<span class="w"> </span>scheduled
<span class="o">[</span>wp<span class="o">]</span><span class="w"> </span>Proved<span class="w"> </span>goals:<span class="w"> </span><span class="m">89</span><span class="w"> </span>/<span class="w"> </span><span class="m">89</span>
<span class="w"> </span>Qed:<span class="w"> </span><span class="m">42</span><span class="w"> </span><span class="o">(</span>4ms-96ms-392ms<span class="o">)</span>
<span class="w"> </span>Alt-Ergo:<span class="w"> </span><span class="m">47</span><span class="w"> </span><span class="o">(</span>12ms-262ms-1.1s<span class="o">)</span><span class="w"> </span><span class="o">(</span><span class="m">131</span><span class="o">)</span>
</code></pre></div>
<p>This program is quite short and simple, so proving it is not such a huge task.
For larger programs things can quickly become tricky.
See for example
<a href="https://github.com/fraunhoferfokus/acsl-by-example/blob/master/VESSEDIA-unique_copy.pdf">this paper</a>
from the people behind <a href="https://www.cs.umd.edu/class/spring2016/cmsc838G/frama-c/ACSL-by-Example-12.1.0.pdf">ACSL by Example</a>,
which formally proves a specialization of <code>std::unique_copy()</code>.</p>
<h2>Ghost code</h2>
<p>Just like with SPARK, it is possible to use so-called "ghost code" to perform special kinds of tasks during verification.
One thing I have found convenient is using ghost code to implement unit tests:</p>
<div class="highlight"><pre><span></span><code><span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// This ghost code acts like a unit test</span>
<span class="w"> </span><span class="cm">/*@ ghost</span>
<span class="cm"> int a0 = isqrt(0) - isqrt2(0);</span>
<span class="cm"> int a1 = isqrt(1) - isqrt2(1);</span>
<span class="cm"> int a2 = isqrt(2) - isqrt2(2);</span>
<span class="cm"> int a3 = isqrt(3) - isqrt2(3);</span>
<span class="cm"> int a4 = isqrt(4) - isqrt2(4);</span>
<span class="cm"> int a5 = isqrt(46340*46340-1) - isqrt2(46340*46340-1);</span>
<span class="cm"> int a6 = isqrt(46340*46340) - isqrt2(46340*46340);</span>
<span class="cm"> int a7 = isqrt(46340*46340+1) - isqrt2(46340*46340+1);</span>
<span class="cm"> int a8 = isqrt(INT_MAX) - isqrt2(INT_MAX);</span>
<span class="cm"> */</span>
<span class="w"> </span><span class="c1">//@ assert a0 == 0;</span>
<span class="w"> </span><span class="c1">//@ assert a1 == 0;</span>
<span class="w"> </span><span class="c1">//@ assert a2 == 0;</span>
<span class="w"> </span><span class="c1">//@ assert a3 == 0;</span>
<span class="w"> </span><span class="c1">//@ assert a4 == 0;</span>
<span class="w"> </span><span class="c1">//@ assert a5 == 0;</span>
<span class="w"> </span><span class="c1">//@ assert a6 == 0;</span>
<span class="w"> </span><span class="c1">//@ assert a7 == 0;</span>
<span class="w"> </span><span class="c1">//@ assert a8 == 0;</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>A more comprehensive test might ensure that \forall integer x; 0 <= x <= INT_MAX ==> isqrt(x) == isqrt2(x),
using a function like this:</p>
<div class="highlight"><pre><span></span><code><span class="cm">/*@ requires 0 <= num <= INT_MAX;</span>
<span class="cm"> ensures \result == 0;</span>
<span class="cm"> assigns \nothing;</span>
<span class="cm"> */</span>
<span class="kt">int</span><span class="w"> </span><span class="nf">diff</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">num</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">isqrt</span><span class="p">(</span><span class="n">num</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">isqrt2</span><span class="p">(</span><span class="n">num</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div>
<p>How to actually prove the postcondition in this contract is left as an exercise for the reader.
There might also be a smarter way of putting a "test" like this in the code without having to have an actual function,
but I do not know how yet.</p>
<h2>Dealing with unproven goals</h2>
<p>If you have a problem proving something, you can tell WP to output its reasoning for each goal into a directory with <code>-wp-out</code>:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>frama-c<span class="w"> </span>-wp<span class="w"> </span>-wp-rte<span class="w"> </span>-wp-out<span class="w"> </span>goals<span class="w"> </span>isqrt.c<span class="w"> </span>
<span class="o">[</span>kernel<span class="o">]</span><span class="w"> </span>Parsing<span class="w"> </span>isqrt.c<span class="w"> </span><span class="o">(</span>with<span class="w"> </span>preprocessing<span class="o">)</span>
<span class="o">[</span>rte<span class="o">]</span><span class="w"> </span>annotating<span class="w"> </span><span class="k">function</span><span class="w"> </span>isqrt
<span class="o">[</span>rte<span class="o">]</span><span class="w"> </span>annotating<span class="w"> </span><span class="k">function</span><span class="w"> </span>isqrt2
<span class="o">[</span>rte<span class="o">]</span><span class="w"> </span>annotating<span class="w"> </span><span class="k">function</span><span class="w"> </span>isqrt2_inner
<span class="o">[</span>rte<span class="o">]</span><span class="w"> </span>annotating<span class="w"> </span><span class="k">function</span><span class="w"> </span>main
<span class="o">[</span>wp<span class="o">]</span><span class="w"> </span><span class="m">46</span><span class="w"> </span>goals<span class="w"> </span>scheduled
<span class="o">[</span>wp<span class="o">]</span><span class="w"> </span>Proved<span class="w"> </span>goals:<span class="w"> </span><span class="m">46</span><span class="w"> </span>/<span class="w"> </span><span class="m">46</span>
<span class="w"> </span>Qed:<span class="w"> </span><span class="m">24</span><span class="w"> </span><span class="o">(</span>4ms-16ms-68ms<span class="o">)</span>
<span class="w"> </span>Alt-Ergo:<span class="w"> </span><span class="m">22</span><span class="w"> </span><span class="o">(</span>16ms-34ms-148ms<span class="o">)</span><span class="w"> </span><span class="o">(</span><span class="m">62</span><span class="o">)</span>
$<span class="w"> </span>ls<span class="w"> </span>goals/typed/<span class="w"> </span>
isqrt2_call_isqrt2_inner_pre_2_Alt-Ergo.mlw<span class="w"> </span>isqrt2_post_Alt-Ergo.mlw
isqrt2_call_isqrt2_inner_pre_2_Alt-Ergo.out<span class="w"> </span>isqrt2_post_Alt-Ergo.out
isqrt2_call_isqrt2_inner_pre_2.ergo<span class="w"> </span>isqrt2_post.ergo
isqrt2_inner_assert_rte_signed_overflow_2_Alt-Ergo.mlw<span class="w"> </span>isqrt_assert_rte_signed_overflow_2_Alt-Ergo.mlw
isqrt2_inner_assert_rte_signed_overflow_2_Alt-Ergo.out<span class="w"> </span>isqrt_assert_rte_signed_overflow_2_Alt-Ergo.out
isqrt2_inner_assert_rte_signed_overflow_2.ergo<span class="w"> </span>isqrt_assert_rte_signed_overflow_2.ergo
<span class="o">[</span>...<span class="o">]</span>
isqrt2_post_2_Alt-Ergo.mlw<span class="w"> </span>isqrt_post_Alt-Ergo.mlw
isqrt2_post_2_Alt-Ergo.out<span class="w"> </span>isqrt_post_Alt-Ergo.out
isqrt2_post_2.ergo<span class="w"> </span>isqrt_post.ergo
</code></pre></div>
<p>We can see that WP made use of Qed and Alt-Ergo to successfully prove all goals.
Let's take a look at <code>isqrt_post.ergo</code>:</p>
<div class="highlight"><pre><span></span><code><span class="p">(</span><span class="o">*</span><span class="w"> </span><span class="o">----------------------------------------------------------</span><span class="w"> </span><span class="o">*</span><span class="p">)</span>
<span class="p">(</span><span class="o">*</span><span class="w"> </span><span class="o">---</span><span class="w"> </span><span class="n">Post</span><span class="o">-</span><span class="n">condition</span><span class="w"> </span><span class="p">(</span><span class="n">file</span><span class="w"> </span><span class="n">isqrt</span><span class="p">.</span><span class="n">c</span><span class="p">,</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="mi">4</span><span class="p">)</span><span class="w"> </span><span class="kr">in</span><span class="w"> </span><span class="s">'isqrt'</span><span class="w"> </span><span class="o">---</span><span class="w"> </span><span class="o">*</span><span class="p">)</span>
<span class="p">(</span><span class="o">*</span><span class="w"> </span><span class="o">----------------------------------------------------------</span><span class="w"> </span><span class="o">*</span><span class="p">)</span>
<span class="n">goal</span><span class="w"> </span><span class="n">isqrt_post</span><span class="o">:</span>
<span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">i_3</span><span class="p">,</span><span class="n">i_2</span><span class="p">,</span><span class="n">i_1</span><span class="p">,</span><span class="n">i</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">int</span><span class="p">.</span>
<span class="w"> </span><span class="n">let</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="mi">1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">i_1</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">int</span><span class="w"> </span><span class="kr">in</span>
<span class="w"> </span><span class="n">let</span><span class="w"> </span><span class="n">x_1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">i_1</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">i_1</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">int</span><span class="w"> </span><span class="kr">in</span>
<span class="w"> </span><span class="n">let</span><span class="w"> </span><span class="n">x_2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">to_sint32</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">int</span><span class="w"> </span><span class="kr">in</span>
<span class="w"> </span><span class="n">let</span><span class="w"> </span><span class="n">x_3</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">x_2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">x_2</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">int</span><span class="w"> </span><span class="kr">in</span>
<span class="w"> </span><span class="p">(</span><span class="mi">0</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="o">-></span>
<span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="mi">2147483647</span><span class="p">)</span><span class="w"> </span><span class="o">-></span>
<span class="w"> </span><span class="n">is_sint32</span><span class="p">(</span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="o">-></span>
<span class="w"> </span><span class="n">is_sint32</span><span class="p">(</span><span class="n">i_1</span><span class="p">)</span><span class="w"> </span><span class="o">-></span>
<span class="w"> </span><span class="n">is_sint32</span><span class="p">(</span><span class="n">i_2</span><span class="p">)</span><span class="w"> </span><span class="o">-></span>
<span class="w"> </span><span class="n">is_sint32</span><span class="p">(</span><span class="n">i_3</span><span class="p">)</span><span class="w"> </span><span class="o">-></span>
<span class="w"> </span><span class="p">(((</span><span class="n">i</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="p">(</span><span class="n">i_1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">i</span><span class="p">))</span><span class="w"> </span><span class="kr">and</span>
<span class="w"> </span><span class="p">((</span><span class="mi">2</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="o">-></span>
<span class="w"> </span><span class="p">(((</span><span class="n">i_3</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">i_3</span><span class="p">)</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="kr">and</span>
<span class="w"> </span><span class="p">(((</span><span class="mi">46340</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">i_3</span><span class="p">)</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="p">(</span><span class="n">i_1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">46340</span><span class="p">))</span><span class="w"> </span><span class="kr">and</span>
<span class="w"> </span><span class="p">((</span><span class="n">i_3</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="mi">46339</span><span class="p">)</span><span class="w"> </span><span class="o">-></span>
<span class="w"> </span><span class="p">((</span><span class="n">i_2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">i_1</span><span class="p">)</span><span class="w"> </span><span class="kr">and</span><span class="w"> </span><span class="p">(</span><span class="n">i_3</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">i_1</span><span class="p">)</span><span class="w"> </span><span class="kr">and</span><span class="w"> </span><span class="p">(</span><span class="n">i_3</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">i_2</span><span class="p">)</span><span class="w"> </span><span class="kr">and</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">x</span><span class="p">))</span><span class="w"> </span><span class="kr">and</span>
<span class="w"> </span><span class="p">(</span><span class="n">i_1</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="mi">2147483646</span><span class="p">)</span><span class="w"> </span><span class="kr">and</span><span class="w"> </span><span class="p">((</span><span class="o">-</span><span class="mi">2147483648</span><span class="p">)</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">x_1</span><span class="p">)</span><span class="w"> </span><span class="kr">and</span>
<span class="w"> </span><span class="p">(</span><span class="n">x_1</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="mi">2147483647</span><span class="p">)</span><span class="w"> </span><span class="kr">and</span><span class="w"> </span><span class="p">((</span><span class="o">-</span><span class="mi">2147483648</span><span class="p">)</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">x_3</span><span class="p">)</span><span class="w"> </span><span class="kr">and</span>
<span class="w"> </span><span class="p">(</span><span class="n">x_3</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="mi">2147483647</span><span class="p">)))))))</span><span class="w"> </span><span class="o">-></span>
<span class="w"> </span><span class="p">((</span><span class="mi">0</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">i_1</span><span class="p">)</span><span class="w"> </span><span class="kr">and</span><span class="w"> </span><span class="p">(</span><span class="n">i_1</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="mi">46340</span><span class="p">))</span>
</code></pre></div>
<p>In many cases it is possible, if you squint just right, to see why Alt-Ergo is not "connecting the dots".
It might be a cast that's confusing it, or it might not be able to rule out that two pointers don't alias.
In this case everything is fine.</p>
<h2>Issues</h2>
<p>There are some pain points I have discovered, which I will list in this section.</p>
<h3>Strings and aliasing</h3>
<p>Lately I've been struggling with string manipulation in ACSL,
for example proving that a function which tokenizes a string into an array of tokens behaves correctly.
Part of that work is hampered by WP (or Alt-Ergo?) seemingly not being able to keep track of whether char pointers alias or not.
Despite putting a precondition that all pointers given must not alias (\separated),
string manipulations inside the function leads to WP/Alt-Ergo thinking that they may suddenly possibly have become aliased.
It also commonly thinks pointers to the heap, .bss or .data areas may alias data on the stack,
which is highly annoying.</p>
<p>It is possible I'm doing something wrong of course, but I felt I should at least put here that
aliasing can be a bit of a pain, which makes manipulating C strings difficult.</p>
<h3>Termination</h3>
<p>By default Frama-C assumes all functions terminate.
It is possible to specify under which conditions a function might not terminate,
which is useful in some cases.
It is also possible to fulfill a contract without the function ever actually returning.
For example, this is valid:</p>
<div class="highlight"><pre><span></span><code><span class="cm">/*@ requires 1 <= lo < hi <= 46340;</span>
<span class="cm"> requires lo*lo <= num < hi*hi;</span>
<span class="cm"> ensures lo <= \result < hi;</span>
<span class="cm"> ensures \result*\result <= num < (\result+1)*(\result+1);</span>
<span class="cm"> assigns \nothing;</span>
<span class="cm"> */</span>
<span class="kt">int</span><span class="w"> </span><span class="nf">isqrt2_inner</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">num</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">lo</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">hi</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">//infinite recursion!</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">isqrt2_inner</span><span class="p">(</span><span class="n">num</span><span class="p">,</span><span class="w"> </span><span class="n">lo</span><span class="p">,</span><span class="w"> </span><span class="n">hi</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div>
<p>I have not yet found any way to have <code>frama-c</code> complain about possible infinite recursion.</p>
<h3>Verification times</h3>
<p>One thing to be aware of is that compared to compilation, running Frama-C can take quite a while:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span><span class="nb">time</span><span class="w"> </span>gcc<span class="w"> </span>isqrt.c<span class="w"> </span>
real<span class="w"> </span>0m0,086s
user<span class="w"> </span>0m0,060s
sys<span class="w"> </span>0m0,016s
$<span class="w"> </span><span class="nb">time</span><span class="w"> </span>frama-c<span class="w"> </span>-wp<span class="w"> </span>-wp-rte<span class="w"> </span>-wp-out<span class="w"> </span>goals<span class="w"> </span>isqrt.c<span class="w"> </span>><span class="w"> </span>/dev/null
real<span class="w"> </span>0m12,766s
user<span class="w"> </span>0m20,500s
sys<span class="w"> </span>0m1,300s
</code></pre></div>
<p>Even for small programs this quickly adds up to minutes.
Putting functions into their own compilation/verification units and using a competent build system is therefore a good idea.</p>
<h2>Conclusions</h2>
<p>Frama-C can be used to verify C code, which is useful in many cases.
Doing so takes considerable developer effort, but provides peace of mind.
Libraries with simple APIs that are used by many people are a good fit, such as libc.</p>
<p>Frama-C is not a panacea, since it says nothing about how long a program might take to execute.
Infinite recursion is one example of this.
Another could be certain degenerate files generated by fuzzers, which might cause a program to do much more work than usual.</p>
<p>Finally, it might not be feasible to define the entire behavior of a program or sets of programs using ACSL.
For example, that compressing and decompressing a file results in the same output as input.
For that it is probably better to use functional tests.</p>
<h2 id="comments">Comments</h2>
<p>I got some comments when I submitted this post to the [Frama-c-discuss] mailing list,
click <a href="https://lists.gforge.inria.fr/pipermail/frama-c-discuss/2018-November/005532.html">here</a> for my initial post and <a href="https://lists.gforge.inria.fr/pipermail/frama-c-discuss/2018-November/thread.html#5532">here</a> to see the entire thread.
<a href="https://lists.gforge.inria.fr/pipermail/frama-c-discuss/2018-November/005533.html">Virgile Prevosto</a> had probably the most relevant comment:</p>
<div class="highlight"><pre><span></span><code><span class="n">Hello</span><span class="w"> </span><span class="n">Tomas</span><span class="p">,</span>
<span class="n">Thanks</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">sharing</span><span class="w"> </span><span class="n">your</span><span class="w"> </span><span class="n">experience</span><span class="o">.</span><span class="w"> </span><span class="n">It</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">always</span><span class="w"> </span><span class="n">interesting</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">us</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">have</span>
<span class="n">feedback</span><span class="w"> </span><span class="n">on</span><span class="w"> </span><span class="n">how</span><span class="w"> </span><span class="n">Frama</span><span class="o">-</span><span class="n">C</span><span class="w"> </span><span class="n">gets</span><span class="w"> </span><span class="n">used</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">order</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">understand</span><span class="w"> </span><span class="n">where</span><span class="w"> </span><span class="n">improvements</span>
<span class="n">would</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">most</span><span class="w"> </span><span class="n">useful</span><span class="p">(</span><span class="o">*</span><span class="p">)</span>
<span class="n">In</span><span class="w"> </span><span class="n">particular</span><span class="p">,</span><span class="w"> </span><span class="n">your</span><span class="w"> </span><span class="n">point</span><span class="w"> </span><span class="n">about</span><span class="w"> </span><span class="n">separation</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">strings</span><span class="w"> </span><span class="n">warrant</span><span class="w"> </span><span class="n">some</span><span class="w"> </span><span class="n">thinking</span>
<span class="n">about</span><span class="w"> </span>\<span class="n">separated</span><span class="w"> </span><span class="n">hypotheses</span><span class="w"> </span><span class="n">that</span><span class="w"> </span><span class="n">can</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">safely</span><span class="w"> </span><span class="n">made</span><span class="w"> </span><span class="n">by</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">memory</span><span class="w"> </span><span class="n">models</span><span class="w"> </span><span class="n">of</span>
<span class="n">WP</span><span class="o">.</span><span class="w"> </span><span class="n">Regarding</span><span class="w"> </span><span class="n">termination</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">recursive</span><span class="w"> </span><span class="n">functions</span><span class="p">,</span><span class="w"> </span><span class="n">this</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">indeed</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="n">yet</span>
<span class="n">implemented</span><span class="w"> </span><span class="n">by</span><span class="w"> </span><span class="n">WP</span><span class="p">,</span><span class="w"> </span><span class="n">but</span><span class="w"> </span><span class="n">ACSL</span><span class="w"> </span><span class="n">introduces</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">decreases</span><span class="w"> </span><span class="n">clause</span><span class="p">,</span><span class="w"> </span><span class="n">which</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">similar</span>
<span class="n">to</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">loop</span><span class="w"> </span><span class="n">variant</span><span class="p">:</span><span class="w"> </span><span class="n">any</span><span class="w"> </span><span class="n">recursive</span><span class="w"> </span><span class="n">call</span><span class="w"> </span><span class="n">must</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">done</span><span class="w"> </span><span class="n">on</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">strictly</span><span class="w"> </span><span class="n">smaller</span>
<span class="s1">'decreases'</span><span class="w"> </span><span class="n">term</span><span class="w"> </span><span class="n">than</span><span class="w"> </span><span class="n">its</span><span class="w"> </span><span class="n">direct</span><span class="w"> </span><span class="n">caller</span><span class="p">,</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">that</span><span class="w"> </span><span class="n">term</span><span class="w"> </span><span class="n">must</span><span class="w"> </span><span class="n">stay</span><span class="w"> </span><span class="n">positive</span><span class="o">.</span>
<span class="n">Currently</span><span class="p">,</span><span class="w"> </span><span class="n">WP</span><span class="w"> </span><span class="n">will</span><span class="w"> </span><span class="n">emit</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">warning</span><span class="w"> </span><span class="n">message</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">it</span><span class="w"> </span><span class="n">encounters</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">decreases</span>
<span class="n">clause</span><span class="p">,</span><span class="w"> </span><span class="n">saying</span><span class="w"> </span><span class="n">that</span><span class="w"> </span><span class="n">this</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">unsupported</span><span class="o">.</span><span class="w"> </span><span class="n">However</span><span class="p">,</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">single</span><span class="w"> </span><span class="n">recursive</span>
<span class="n">functions</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">simple</span><span class="w"> </span><span class="n">syntactic</span><span class="w"> </span><span class="n">transformation</span><span class="w"> </span><span class="n">should</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">able</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">generate</span><span class="w"> </span><span class="n">an</span>
<span class="n">ACSL</span><span class="w"> </span><span class="n">assertion</span><span class="w"> </span><span class="n">at</span><span class="w"> </span><span class="n">each</span><span class="w"> </span><span class="n">recursive</span><span class="w"> </span><span class="n">call</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">content</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">decreases</span>
<span class="n">clause</span><span class="o">.</span><span class="w"> </span><span class="n">For</span><span class="w"> </span><span class="n">mutual</span><span class="w"> </span><span class="n">recursion</span><span class="p">,</span><span class="w"> </span><span class="n">things</span><span class="w"> </span><span class="n">are</span><span class="w"> </span><span class="n">slightly</span><span class="w"> </span><span class="n">more</span><span class="w"> </span><span class="n">tricky</span><span class="w"> </span><span class="p">(</span><span class="n">you</span><span class="w"> </span><span class="n">have</span><span class="w"> </span><span class="n">to</span>
<span class="n">identify</span><span class="w"> </span><span class="n">all</span><span class="w"> </span><span class="n">functions</span><span class="w"> </span><span class="n">involved</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">recursion</span><span class="p">),</span><span class="w"> </span><span class="n">but</span><span class="w"> </span><span class="n">this</span><span class="w"> </span><span class="n">should</span><span class="w"> </span><span class="n">be</span>
<span class="n">doable</span><span class="o">.</span>
<span class="n">Finally</span><span class="p">,</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">point</span><span class="w"> </span><span class="n">about</span><span class="w"> </span><span class="n">verification</span><span class="w"> </span><span class="n">time</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">just</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">matter</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">perspective</span><span class="p">:</span>
<span class="n">just</span><span class="w"> </span><span class="n">wait</span><span class="w"> </span><span class="n">until</span><span class="w"> </span><span class="n">Frama</span><span class="o">-</span><span class="n">C</span><span class="w"> </span><span class="n">get</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">proper</span><span class="w"> </span><span class="n">C</span><span class="o">++</span><span class="w"> </span><span class="n">front</span><span class="o">-</span><span class="n">end</span><span class="p">,</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">I</span><span class="s1">'m sure we will be</span>
<span class="n">able</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">have</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">smaller</span><span class="w"> </span><span class="n">execution</span><span class="w"> </span><span class="n">time</span><span class="w"> </span><span class="n">than</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="p">(</span><span class="n">C</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="n">compiler</span><span class="w"> </span><span class="err">😝</span><span class="o">.</span><span class="w"> </span><span class="n">On</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">more</span>
<span class="n">serious</span><span class="w"> </span><span class="n">note</span><span class="p">,</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">was</span><span class="w"> </span><span class="n">highlighted</span><span class="w"> </span><span class="n">by</span><span class="w"> </span><span class="n">one</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">our</span><span class="w"> </span><span class="n">partners</span><span class="p">,</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">comparison</span>
<span class="n">should</span><span class="w"> </span><span class="n">rather</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">done</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">time</span><span class="w"> </span><span class="n">taken</span><span class="w"> </span><span class="n">by</span><span class="w"> </span><span class="n">running</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">test</span><span class="w"> </span><span class="n">suite</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="n">an</span>
<span class="n">extremely</span><span class="w"> </span><span class="n">high</span><span class="w"> </span><span class="n">level</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">coverage</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">task</span><span class="w"> </span><span class="n">which</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="n">exactly</span><span class="w"> </span><span class="n">free</span><span class="o">.</span><span class="w"> </span><span class="n">Of</span>
<span class="n">course</span><span class="p">,</span><span class="w"> </span><span class="n">this</span><span class="w"> </span><span class="n">does</span><span class="w"> </span><span class="ow">not</span><span class="w"> </span><span class="n">preclude</span><span class="w"> </span><span class="n">us</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="n">trying</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">achieve</span><span class="w"> </span><span class="n">better</span>
<span class="n">performances</span><span class="p">,</span><span class="w"> </span><span class="n">but</span><span class="w"> </span><span class="n">formal</span><span class="w"> </span><span class="n">verification</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">unlikely</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">become</span><span class="w"> </span><span class="n">costless</span><span class="w"> </span><span class="n">at</span>
<span class="n">some</span><span class="w"> </span><span class="n">point</span><span class="o">.</span>
<span class="n">Thanks</span><span class="w"> </span><span class="n">again</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">your</span><span class="w"> </span><span class="n">post</span><span class="p">,</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">feel</span><span class="w"> </span><span class="n">free</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">ask</span><span class="w"> </span><span class="n">further</span><span class="w"> </span><span class="n">questions</span><span class="w"> </span><span class="n">on</span>
<span class="n">Frama</span><span class="o">-</span><span class="n">C</span><span class="o">.</span>
<span class="n">Best</span><span class="w"> </span><span class="n">regards</span><span class="p">,</span>
</code></pre></div>
<h2>Appendix</h2>
<p><code>isqrt.c</code>:</p>
<div class="highlight"><pre><span></span><code><span class="cp">#include</span><span class="w"> </span><span class="cpf"><limits.h></span>
<span class="cm">/*@ requires 0 <= num <= INT_MAX;</span>
<span class="cm"> ensures 0 <= \result <= 46340; //WP doesn't need this, but it's nice for users to know</span>
<span class="cm"> ensures \result*\result <= num < (\result+1)*(\result+1);</span>
<span class="cm"> assigns \nothing;</span>
<span class="cm"> */</span>
<span class="kt">int</span><span class="w"> </span><span class="nf">isqrt</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">num</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">num</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">2</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">num</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="cm">/*@ loop assigns i;</span>
<span class="cm"> loop invariant i*i <= num;</span>
<span class="cm"> loop variant 46340-i;</span>
<span class="cm"> */</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">46340</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">num</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">i</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">46340</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/*@ requires 1 <= lo < hi <= 46340;</span>
<span class="cm"> requires lo*lo <= num < hi*hi;</span>
<span class="cm"> ensures lo <= \result < hi;</span>
<span class="cm"> ensures \result*\result <= num < (\result+1)*(\result+1);</span>
<span class="cm"> assigns \nothing;</span>
<span class="cm"> */</span>
<span class="kt">int</span><span class="w"> </span><span class="nf">isqrt2_inner</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">num</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">lo</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">hi</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">lo</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">hi</span><span class="mi">-1</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">lo</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">mid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">lo</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">hi</span><span class="p">)</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mi">2</span><span class="p">;</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">mid</span><span class="o">*</span><span class="n">mid</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="n">num</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">isqrt2_inner</span><span class="p">(</span><span class="n">num</span><span class="p">,</span><span class="w"> </span><span class="n">lo</span><span class="p">,</span><span class="w"> </span><span class="n">mid</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">isqrt2_inner</span><span class="p">(</span><span class="n">num</span><span class="p">,</span><span class="w"> </span><span class="n">mid</span><span class="p">,</span><span class="w"> </span><span class="n">hi</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
<span class="cm">/*@ requires 0 <= num <= INT_MAX;</span>
<span class="cm"> ensures 0 <= \result <= 46340;</span>
<span class="cm"> ensures \result*\result <= num < (\result+1)*(\result+1);</span>
<span class="cm"> assigns \nothing;</span>
<span class="cm"> */</span>
<span class="kt">int</span><span class="w"> </span><span class="nf">isqrt2</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">num</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">num</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">2</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">num</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">num</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="mi">46340</span><span class="o">*</span><span class="mi">46340</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">46340</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">isqrt2_inner</span><span class="p">(</span><span class="n">num</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">46340</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// This ghost code acts like a unit test</span>
<span class="w"> </span><span class="cm">/*@ ghost</span>
<span class="cm"> int a0 = isqrt(0) - isqrt2(0);</span>
<span class="cm"> int a1 = isqrt(1) - isqrt2(1);</span>
<span class="cm"> int a2 = isqrt(2) - isqrt2(2);</span>
<span class="cm"> int a3 = isqrt(3) - isqrt2(3);</span>
<span class="cm"> int a4 = isqrt(4) - isqrt2(4);</span>
<span class="cm"> int a5 = isqrt(46340*46340-1) - isqrt2(46340*46340-1);</span>
<span class="cm"> int a6 = isqrt(46340*46340) - isqrt2(46340*46340);</span>
<span class="cm"> int a7 = isqrt(46340*46340+1) - isqrt2(46340*46340+1);</span>
<span class="cm"> int a8 = isqrt(INT_MAX) - isqrt2(INT_MAX);</span>
<span class="cm"> */</span>
<span class="w"> </span><span class="c1">//@ assert a0 == 0;</span>
<span class="w"> </span><span class="c1">//@ assert a1 == 0;</span>
<span class="w"> </span><span class="c1">//@ assert a2 == 0;</span>
<span class="w"> </span><span class="c1">//@ assert a3 == 0;</span>
<span class="w"> </span><span class="c1">//@ assert a4 == 0;</span>
<span class="w"> </span><span class="c1">//@ assert a5 == 0;</span>
<span class="w"> </span><span class="c1">//@ assert a6 == 0;</span>
<span class="w"> </span><span class="c1">//@ assert a7 == 0;</span>
<span class="w"> </span><span class="c1">//@ assert a8 == 0;</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>grey screen with no music2018-08-31T00:00:00+02:002018-08-31T00:00:00+02:00tomastag:www.härdin.se,2018-08-31:/demoscene/2018/08/31/grey-screen-with-no-music/<p>More pouet BBS nonsense.</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code><span class="mf">16</span><span class="w"> </span><span class="n">bytes</span>
<span class="n">Use</span><span class="w"> </span><span class="n">black</span><span class="o">/</span><span class="n">white</span><span class="w"> </span><span class="n">TV</span><span class="w"> </span><span class="kr">for</span><span class="w"> </span><span class="n">proper</span><span class="w"> </span><span class="n">grayness</span>
</code></pre></div>Rooting and installing LineageOS on a Samsung Galaxy S52018-08-25T15:14:52+02:002018-08-25T15:14:52+02:00tomastag:www.härdin.se,2018-08-25:/blog/2018/08/25/rooting-and-installing-lineageos-on-a-samsung-galaxy-s5/<p>A few days ago the screen on my Sony Xperia Z2 Compact broke,
after a long line of other problems with it
(both charging ports breaking, broken TRS jack, broken camera, port covers coming loose etc).
I tried to triage the screen cracking with superglue, but all that accomplished was …</p><p>A few days ago the screen on my Sony Xperia Z2 Compact broke,
after a long line of other problems with it
(both charging ports breaking, broken TRS jack, broken camera, port covers coming loose etc).
I tried to triage the screen cracking with superglue, but all that accomplished was make the phone look awful:</p>
<p><a href="http://www.härdin.se/images/P8261874.JPG"><img alt="Xperia with cracked, glued screen and OTG cable now required for interfacing with it" src="http://www.härdin.se/images/tP8261874.JPG"></a></p>
<p>I decided it was time for something else, preferably something that gives me more control than the non-rooted Xperia.
I ended up trading a friend of mine a few beers for his old Samsung Galaxy S5,
partly to have something while shopping around for a used <a href="https://www.fairphone.com/">Fairphone</a> or waiting for the <a href="https://puri.sm/shop/librem-5/">Librem 5</a>.
The S5 is quite rootable though, and LineageOS supports it,
so I decided to go for it instead.
This also has the upside of saving money and saving the S5 from becoming e-waste.</p>
<p>For the most part I followed <a href="https://wiki.lineageos.org/devices/klte/install">this guide on lineageos.org</a>.
It might help knowing my device (SM-G900F) is known as klte in TWRP and Lineage circles.
First up was making sure Heimdall worked correctly by issuing the <em>print-pit</em> command:</p>
<div class="highlight"><pre><span></span><code><span class="o">$</span><span class="w"> </span><span class="n">heimdall</span><span class="w"> </span><span class="nb">print</span><span class="o">-</span><span class="n">pit</span>
<span class="n">Heimdall</span><span class="w"> </span><span class="n">v1</span><span class="o">.</span><span class="mf">4.1</span>
<span class="n">Copyright</span><span class="w"> </span><span class="p">(</span><span class="n">c</span><span class="p">)</span><span class="w"> </span><span class="mi">2010</span><span class="o">-</span><span class="mi">2014</span><span class="w"> </span><span class="n">Benjamin</span><span class="w"> </span><span class="n">Dobell</span><span class="p">,</span><span class="w"> </span><span class="n">Glass</span><span class="w"> </span><span class="n">Echidna</span>
<span class="n">http</span><span class="p">:</span><span class="o">//</span><span class="n">www</span><span class="o">.</span><span class="n">glassechidna</span><span class="o">.</span><span class="n">com</span><span class="o">.</span><span class="n">au</span><span class="o">/</span>
<span class="n">This</span><span class="w"> </span><span class="n">software</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">provided</span><span class="w"> </span><span class="n">free</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">charge</span><span class="o">.</span><span class="w"> </span><span class="n">Copying</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">redistribution</span><span class="w"> </span><span class="k">is</span>
<span class="n">encouraged</span><span class="o">.</span>
<span class="n">If</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">appreciate</span><span class="w"> </span><span class="n">this</span><span class="w"> </span><span class="n">software</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">would</span><span class="w"> </span><span class="n">like</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">support</span><span class="w"> </span><span class="n">future</span>
<span class="n">development</span><span class="w"> </span><span class="n">please</span><span class="w"> </span><span class="n">consider</span><span class="w"> </span><span class="n">donating</span><span class="p">:</span>
<span class="n">http</span><span class="p">:</span><span class="o">//</span><span class="n">www</span><span class="o">.</span><span class="n">glassechidna</span><span class="o">.</span><span class="n">com</span><span class="o">.</span><span class="n">au</span><span class="o">/</span><span class="n">donate</span><span class="o">/</span>
<span class="n">Initialising</span><span class="w"> </span><span class="n">connection</span><span class="o">...</span>
<span class="n">Detecting</span><span class="w"> </span><span class="n">device</span><span class="o">...</span>
<span class="n">Claiming</span><span class="w"> </span><span class="n">interface</span><span class="o">...</span>
<span class="n">Setting</span><span class="w"> </span><span class="n">up</span><span class="w"> </span><span class="n">interface</span><span class="o">...</span>
<span class="n">Initialising</span><span class="w"> </span><span class="n">protocol</span><span class="o">...</span>
<span class="n">Protocol</span><span class="w"> </span><span class="n">initialisation</span><span class="w"> </span><span class="n">successful</span><span class="o">.</span>
<span class="n">Beginning</span><span class="w"> </span><span class="n">session</span><span class="o">...</span>
<span class="n">Some</span><span class="w"> </span><span class="n">devices</span><span class="w"> </span><span class="n">may</span><span class="w"> </span><span class="n">take</span><span class="w"> </span><span class="n">up</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="n">minutes</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">respond</span><span class="o">.</span>
<span class="n">Please</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">patient</span><span class="o">!</span>
<span class="n">Session</span><span class="w"> </span><span class="n">begun</span><span class="o">.</span>
<span class="n">Downloading</span><span class="w"> </span><span class="n">device</span><span class="s1">'s PIT file...</span>
<span class="n">ERROR</span><span class="p">:</span><span class="w"> </span><span class="n">Failed</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">send</span><span class="w"> </span><span class="n">request</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">end</span><span class="w"> </span><span class="n">PIT</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">transfer</span><span class="o">!</span>
<span class="n">ERROR</span><span class="p">:</span><span class="w"> </span><span class="n">Failed</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">download</span><span class="w"> </span><span class="n">PIT</span><span class="w"> </span><span class="n">file</span><span class="o">!</span>
<span class="n">Ending</span><span class="w"> </span><span class="n">session</span><span class="o">...</span>
<span class="n">ERROR</span><span class="p">:</span><span class="w"> </span><span class="n">Failed</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">send</span><span class="w"> </span><span class="n">end</span><span class="w"> </span><span class="n">session</span><span class="w"> </span><span class="n">packet</span><span class="o">!</span>
<span class="n">Releasing</span><span class="w"> </span><span class="n">device</span><span class="w"> </span><span class="n">interface</span><span class="o">...</span>
</code></pre></div>
<p>No dice.
Searching around a bit on the Web for the given error message yielded <a href="https://github.com/Benjamin-Dobell/Heimdall/issues/292">a suggestion to build Heimdall from master</a>.
Off I went to the <a href="https://gitlab.com/BenjaminDobell/Heimdall">Heimdall GitLab</a>!</p>
<p>To build Heimdall a number of dependencies had to be installed.
For various reasons I was unable to install Qt5's build deps,
so I only installed the dependencies needed to build the Heimdall CLI:</p>
<div class="highlight"><pre><span></span><code># apt install build-essential cmake zlib1g-dev libusb-1.0-0-dev
</code></pre></div>
<p>Next I configured Heimdall with -DCMAKE_BUILD_TYPE=Release and -DDISABLE_FRONTEND=ON,
leading to a successful compile and a binary under build/bin/heimdall which could successfully perform print-pit:</p>
<div class="highlight"><pre><span></span><code><span class="err">$</span><span class="w"> </span><span class="p">.</span><span class="o">/</span><span class="n">heimdall</span><span class="w"> </span><span class="n">version</span>
<span class="n">v1</span><span class="mf">.4.2</span>
<span class="err">$</span><span class="w"> </span><span class="p">.</span><span class="o">/</span><span class="n">heimdall</span><span class="w"> </span><span class="k">print</span><span class="o">-</span><span class="n">pit</span>
<span class="n">Heimdall</span><span class="w"> </span><span class="n">v1</span><span class="mf">.4.2</span>
<span class="n">Copyright</span><span class="w"> </span><span class="p">(</span><span class="n">c</span><span class="p">)</span><span class="w"> </span><span class="mi">2010</span><span class="o">-</span><span class="mi">2017</span><span class="w"> </span><span class="n">Benjamin</span><span class="w"> </span><span class="n">Dobell</span><span class="p">,</span><span class="w"> </span><span class="n">Glass</span><span class="w"> </span><span class="n">Echidna</span>
<span class="nl">http</span><span class="p">:</span><span class="o">//</span><span class="n">www</span><span class="p">.</span><span class="n">glassechidna</span><span class="p">.</span><span class="n">com</span><span class="p">.</span><span class="n">au</span><span class="o">/</span>
<span class="n">This</span><span class="w"> </span><span class="n">software</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">provided</span><span class="w"> </span><span class="k">free</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">charge</span><span class="p">.</span><span class="w"> </span><span class="n">Copying</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">redistribution</span><span class="w"> </span><span class="k">is</span>
<span class="n">encouraged</span><span class="p">.</span>
<span class="k">If</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">appreciate</span><span class="w"> </span><span class="n">this</span><span class="w"> </span><span class="n">software</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">would</span><span class="w"> </span><span class="ow">like</span><span class="w"> </span><span class="k">to</span><span class="w"> </span><span class="n">support</span><span class="w"> </span><span class="n">future</span>
<span class="n">development</span><span class="w"> </span><span class="n">please</span><span class="w"> </span><span class="n">consider</span><span class="w"> </span><span class="nl">donating</span><span class="p">:</span>
<span class="nl">http</span><span class="p">:</span><span class="o">//</span><span class="n">www</span><span class="p">.</span><span class="n">glassechidna</span><span class="p">.</span><span class="n">com</span><span class="p">.</span><span class="n">au</span><span class="o">/</span><span class="n">donate</span><span class="o">/</span>
<span class="n">Initialising</span><span class="w"> </span><span class="k">connection</span><span class="p">...</span>
<span class="n">Detecting</span><span class="w"> </span><span class="n">device</span><span class="p">...</span>
<span class="n">Claiming</span><span class="w"> </span><span class="n">interface</span><span class="p">...</span>
<span class="n">Setting</span><span class="w"> </span><span class="n">up</span><span class="w"> </span><span class="n">interface</span><span class="p">...</span>
<span class="n">Initialising</span><span class="w"> </span><span class="n">protocol</span><span class="p">...</span>
<span class="n">Protocol</span><span class="w"> </span><span class="n">initialisation</span><span class="w"> </span><span class="n">successful</span><span class="p">.</span>
<span class="n">Beginning</span><span class="w"> </span><span class="k">session</span><span class="p">...</span>
<span class="ow">Some</span><span class="w"> </span><span class="n">devices</span><span class="w"> </span><span class="n">may</span><span class="w"> </span><span class="n">take</span><span class="w"> </span><span class="n">up</span><span class="w"> </span><span class="k">to</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="n">minutes</span><span class="w"> </span><span class="k">to</span><span class="w"> </span><span class="n">respond</span><span class="p">.</span>
<span class="n">Please</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">patient</span><span class="err">!</span>
<span class="k">Session</span><span class="w"> </span><span class="n">begun</span><span class="p">.</span>
<span class="n">Downloading</span><span class="w"> </span><span class="n">device</span><span class="err">'</span><span class="n">s</span><span class="w"> </span><span class="n">PIT</span><span class="w"> </span><span class="k">file</span><span class="p">...</span>
<span class="n">PIT</span><span class="w"> </span><span class="k">file</span><span class="w"> </span><span class="n">download</span><span class="w"> </span><span class="n">successful</span><span class="p">.</span>
<span class="n">Entry</span><span class="w"> </span><span class="nf">Count</span><span class="err">:</span><span class="w"> </span><span class="mi">30</span>
<span class="o">[</span><span class="n">snip</span><span class="o">]</span>
<span class="n">Ending</span><span class="w"> </span><span class="k">session</span><span class="p">...</span>
<span class="n">Rebooting</span><span class="w"> </span><span class="n">device</span><span class="p">...</span>
<span class="n">Releasing</span><span class="w"> </span><span class="n">device</span><span class="w"> </span><span class="n">interface</span><span class="p">...</span>
</code></pre></div>
<p>The time was ripe for flashing twrp-3.2.3-0-klte.img (sha256sum ce7e30871a101f53835d46dc296eb92c2a586e8034f41235b1dfe264eab62326):</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>./heimdall<span class="w"> </span>flash<span class="w"> </span>--RECOVERY<span class="w"> </span>twrp-x.x.x-x-klte.img<span class="w"> </span>--no-reboot
</code></pre></div>
<p>This worked fine, but the phone didn't reboot after flashing like the guide said it would.
I waited a while and rebooted it manually, which worked fine.
Holding Volume Up + Home + Power got me into TWRP to continue the process.
I followed the instructions to wipe and format the device, or as TWRP says: <em>~swipe to wipe~</em></p>
<p>Next I pushed the LineageOS install ZIP and the addonsu ZIP:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>adb<span class="w"> </span>push<span class="w"> </span>lineage-15.1-20180820-nightly-klte-signed.zip<span class="w"> </span>/sdcard/
<span class="o">[</span><span class="m">100</span>%<span class="o">]</span><span class="w"> </span>/sdcard/lineage-15.1-20180820-nightly-klte-signed.zip
$<span class="w"> </span>adb<span class="w"> </span>push<span class="w"> </span>addonsu-15.1-arm-signed.zip<span class="w"> </span>/sdcard/
<span class="o">[</span><span class="m">100</span>%<span class="o">]</span><span class="w"> </span>/sdcard/addonsu-15.1-arm-signed.zip
</code></pre></div>
<p>TWRP was not able to verify the signature on the Lineage ZIP, so I skipped the verification step on both files.
After doing that the installation went fine,
and I was able to successfully boot into Lineage.
Woo!</p>
<p>After this I wanted to install <a href="https://f-droid.org/">F-Droid</a>,
which is like an app store for libre programs.
Android 8 Oreo has made installing unofficial apps a bit more difficult,
so I went with downloading the F-Droid APK via ADB.
To do this I had to enable developer mode and USB debugging on the phone.
After that it was merely a matter of running <code>adb install</code> with a USB cable plugged in:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>adb<span class="w"> </span>install<span class="w"> </span>FDroid.apk
Success
</code></pre></div>
<p>Funnily enough, F-Droid wanted to update even though I grabbed the latest version of it off its website. Oh well.
Here's the final result of all this:</p>
<p><a href="http://www.härdin.se/images/P8261878.JPG"><img alt="Galaxy S5 with Lineage installed" src="http://www.härdin.se/images/tP8261878.JPG"></a></p>
<p>I also had to fiddle with importing my contacts and calendar.
All in all I'd say this was much less painful than I expected.
Having the increased control this setup gives me is great,
and the lack of apps on F-Droid that try to harvest and sell my data and display ads makes me wonder why I didn't do this sooner...</p>
<p>In the future I might fiddle with ways of sandboxing Android apps if I ever need to run any.
Perhaps I can make do with my old broken phone for that -
it's probably a good idea to force myself to use the OTG cable, wireless mouse and keyboad before stooping to using proprietary software!</p>Some site changes2018-08-23T11:36:55+02:002018-08-23T11:36:55+02:00tomastag:www.härdin.se,2018-08-23:/blog/2018/08/23/some-site-changes/<p>Today I felt the site needed a bit more structure, so I've done the following to it:</p>
<ul>
<li>Moved contact information to its own page instead of having it in the site template</li>
<li>Trimmed down the landing page a bit</li>
<li>Added a link to the <a href="/files">file archive</a> in the navbar</li>
<li>Added …</li></ul><p>Today I felt the site needed a bit more structure, so I've done the following to it:</p>
<ul>
<li>Moved contact information to its own page instead of having it in the site template</li>
<li>Trimmed down the landing page a bit</li>
<li>Added a link to the <a href="/files">file archive</a> in the navbar</li>
<li>Added descriptions to some files in the file archive via AddDescription in mod_autoindex</li>
</ul>
<p>Adding descriptions involved some grief since Apache may apply a rule multiple times,
and there is no way to say "only apply this rules once at this level please".
So files like bg2-1.5a-server.zip would get the description for the bg2 folder, which looked very wrong.
The simple solution was to add a rule like:</p>
<div class="highlight"><pre><span></span><code>AddDescription "&nbsp;" *.*
</code></pre></div>
<p>This suppresses descriptions for all files with extensions unless I have added a description
for them explicitly.</p>
<p>I also set the contents of the navbar manually by putting the following in pelicanconf.py:</p>
<div class="highlight"><pre><span></span><code>DISPLAY_CATEGORIES_ON_MENU = False
DISPLAY_PAGES_ON_MENU = False
MENUITEMS = (
('Home','/'),
('Blog','/category/blog.html'),
('Files','/files'),
('Contact','/pages/contact.html'),
)
</code></pre></div>
<p>Future things to do on the site include adding HTTPS support
and adding a demoscene category documenting all my productions ála <a href="https://xayax.net/">xayax.net</a>.</p>libre.solar2018-07-25T22:48:39+02:002018-07-25T22:48:39+02:00tomastag:www.härdin.se,2018-07-25:/blog/2018/07/25/libre-solar/<p>I found <a href="http://libre.solar/">libre.solar</a> today,
which is a nice little collection of open source hardware projects relating to solar power.
So far it includes a maximum power point tracking (MPPT) charger, some battery management boards and a Raspberri Pi CAN interface.
It's nice to see more projects like this aimed …</p><p>I found <a href="http://libre.solar/">libre.solar</a> today,
which is a nice little collection of open source hardware projects relating to solar power.
So far it includes a maximum power point tracking (MPPT) charger, some battery management boards and a Raspberri Pi CAN interface.
It's nice to see more projects like this aimed at renewable energy,
since a lot of the hardware is quite expensive.</p>Dengue Fever2018-07-15T00:00:00+02:002018-07-15T00:00:00+02:00tomastag:www.härdin.se,2018-07-15:/demoscene/2018/07/15/dengue-fever/<p>I sprung the need for music on poor glafouk quite close to the deadline,
but it ended up working out in the end.
The main attraction here is obviously the rotorzoomer.
This reuses the text compressor from the <a href="http://www.härdin.se/demoscene/2012/10/26/sillyventure-2k12-invitro/">SillyVenture 2k12 invitro</a>.
I learned later that the music is a cover …</p><p>I sprung the need for music on poor glafouk quite close to the deadline,
but it ended up working out in the end.
The main attraction here is obviously the rotorzoomer.
This reuses the text compressor from the <a href="http://www.härdin.se/demoscene/2012/10/26/sillyventure-2k12-invitro/">SillyVenture 2k12 invitro</a>.
I learned later that the music is a cover of a Madonna song (sneaky glafouk!)</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code>Dengue Fever
a 4k Atari 2600 VCS one-screener
code and graphics by Tjoppen^DSS
music by Glafouk^Flush
released at High Coast Hack Summer 2018
http://hch.a1200.se/
</code></pre></div>Solar mount version 62018-05-16T13:40:19+02:002018-05-16T13:40:19+02:00tomastag:www.härdin.se,2018-05-16:/blog/2018/05/16/solar-mount-version-6/<p>Even simpler design this time.
Decided to bring it closer to the ground to decrease the amount of lumber needed.
For ten 1.0x1.6 meter panels this design needs 74 meters of 45x145 mm lumber,
at a cost of 1840 SEK (210 USD).
Making a 45x95 mm variant shouldn't …</p><p>Even simpler design this time.
Decided to bring it closer to the ground to decrease the amount of lumber needed.
For ten 1.0x1.6 meter panels this design needs 74 meters of 45x145 mm lumber,
at a cost of 1840 SEK (210 USD).
Making a 45x95 mm variant shouldn't be too hard, but 45x145 is what I have in my barn.</p>
<p><img alt="Solar panel mount version 6" src="http://www.härdin.se/images/solar_mount6.png" title="Solar panel mount version 6"></p>
<p>As always, you can find the source files on <a href="https://github.com/Tjoppen/solar_stuff/">GitHub</a>
or download them in zip form <a href="http://www.härdin.se/files/blog/solar_stuff_2.zip">here</a></p>Accept-Language test2018-05-16T11:30:27+02:002018-05-16T11:30:27+02:00tomastag:www.härdin.se,2018-05-16:/blog/2018/05/16/accept-language-test/<p>This is a quick test of using MultiViews in apache2 to serve two versions of this article:
this version in English and another in Swedish.
Which one you see depends on what your browser has sent in the Accept-Language HTTP header.
You can get the Swedish version by clicking "sv …</p><p>This is a quick test of using MultiViews in apache2 to serve two versions of this article:
this version in English and another in Swedish.
Which one you see depends on what your browser has sent in the Accept-Language HTTP header.
You can get the Swedish version by clicking "sv" in "Translations" further up.</p>
<p>In order to get this working right I had to fiddle around with pelican in a number of ways.
First I had to edit pelicanconf.py and change the output filenames and URLs like so:</p>
<div class="highlight"><pre><span></span><code><span class="n">ARTICLE_URL</span> <span class="o">=</span> <span class="s1">'</span><span class="si">{category}</span><span class="s1">/{date:%Y}/{date:%m}/{date:</span><span class="si">%d</span><span class="s1">}/</span><span class="si">{slug}</span><span class="s1">/'</span>
<span class="n">ARTICLE_SAVE_AS</span> <span class="o">=</span> <span class="n">ARTICLE_URL</span> <span class="o">+</span> <span class="s1">'index.html.en'</span>
<span class="n">ARTICLE_LANG_URL</span> <span class="o">=</span> <span class="n">ARTICLE_URL</span> <span class="o">+</span> <span class="s1">'index.html.</span><span class="si">{lang}</span><span class="s1">'</span>
<span class="n">ARTICLE_LANG_SAVE_AS</span> <span class="o">=</span> <span class="n">ARTICLE_URL</span> <span class="o">+</span> <span class="s1">'index.html.</span><span class="si">{lang}</span><span class="s1">'</span>
</code></pre></div>
<p>The ARTICLE_LANG_URL thing is probably not necessary, as we shall see.</p>
<p>I tried various ways to get "Translations" to always link to the other translation explicitly (sv -> en and vice versa).
This didn't end up working, so I just hardcoded the template to insert links to both language variants if there are translations available.
Since I am only going to write content in English or Swedish, always linking to index.html.en and index.html.sv was enough.
This site is based on the notmyidea template,
so I replaced the content of notmyidea/templates/translations.html with:</p>
<div class="highlight"><pre><span></span><code>{% macro translations_for(article) %}
{% if article.translations %}
Translations: <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"index.html.en"</span><span class="p">></span>en<span class="p"></</span><span class="nt">a</span><span class="p">></span>, <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"index.html.sv"</span><span class="p">></span>sv<span class="p"></</span><span class="nt">a</span><span class="p">></span>
{% endif %}
{% endmacro %}
</code></pre></div>
<p>That should be about it ☺</p>Accept-Language test2018-05-16T11:30:27+02:002018-05-16T11:30:27+02:00tomastag:www.härdin.se,2018-05-16:/blog/2018/05/16/accept-language-test/index.html.sv<p>Detta är ett snabbt test med att använda MultiViews i apache2 för att leverera två versioner
av denna artikel: denna version på svenska och en annan version på engelska.
Vilken version du ser beror på vad din webbläsare har skickat i Accept-Language HTTP-headern.
Du kan få den engelska versionen genom …</p><p>Detta är ett snabbt test med att använda MultiViews i apache2 för att leverera två versioner
av denna artikel: denna version på svenska och en annan version på engelska.
Vilken version du ser beror på vad din webbläsare har skickat i Accept-Language HTTP-headern.
Du kan få den engelska versionen genom att klicka på "en" i "Translations" längre upp.</p>
<p>För att få detta att fungera så var jag tvingen att fippla en del med pelican.
Först redigerade jag pelicanconf.py och ändrade filnamn och URL:er på följande vis:</p>
<div class="highlight"><pre><span></span><code><span class="n">ARTICLE_URL</span> <span class="o">=</span> <span class="s1">'</span><span class="si">{category}</span><span class="s1">/{date:%Y}/{date:%m}/{date:</span><span class="si">%d</span><span class="s1">}/</span><span class="si">{slug}</span><span class="s1">/'</span>
<span class="n">ARTICLE_SAVE_AS</span> <span class="o">=</span> <span class="n">ARTICLE_URL</span> <span class="o">+</span> <span class="s1">'index.html.en'</span>
<span class="n">ARTICLE_LANG_URL</span> <span class="o">=</span> <span class="n">ARTICLE_URL</span> <span class="o">+</span> <span class="s1">'index.html.</span><span class="si">{lang}</span><span class="s1">'</span>
<span class="n">ARTICLE_LANG_SAVE_AS</span> <span class="o">=</span> <span class="n">ARTICLE_URL</span> <span class="o">+</span> <span class="s1">'index.html.</span><span class="si">{lang}</span><span class="s1">'</span>
</code></pre></div>
<p>ARTICLE_LANG_URL är troligtvis inte nödvändigt, vilket vi snart kommer att se varför.</p>
<p>Jag försökte med lite olika sätt att få "Translations" att altid länka till den andra översättningen explicit (sv -> en och vice versa).
Detta visade sig att inte gå att få till, så jag hårdkodade istället templaten så att det petar in
länkar till båda språkvarianter om det finns översättningar tillgängliga.
Eftersom jag endast kommer skriva innehåll på svenska eller engelska, så räckte det med att alltid
länka index.html.en och index.html.sv.
Den här sidan är baserad på notmyidea-templaten,
så jag bytte innehållet i i notmyidea/templates/translations.html till:</p>
<div class="highlight"><pre><span></span><code>{% macro translations_for(article) %}
{% if article.translations %}
Translations: <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"index.html.en"</span><span class="p">></span>en<span class="p"></</span><span class="nt">a</span><span class="p">></span>, <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"index.html.sv"</span><span class="p">></span>sv<span class="p"></</span><span class="nt">a</span><span class="p">></span>
{% endif %}
{% endmacro %}
</code></pre></div>
<p>Det borde vara allt som krävs på ett ungefär ☺</p>SAQ follow-up: no luck!2018-05-15T18:48:37+02:002018-05-15T18:48:37+02:00tomastag:www.härdin.se,2018-05-15:/blog/2018/05/15/saq-follow-up-no-luck/<p>Just a quick after-the-fact update to the
<a href="http://www.härdin.se/blog/2018/04/25/saq-receiver-in-gnu-radio/">previous post</a>
about trying to receive the Swedish world heritage VLF transmitter SAQ in Varberg.
Me, SA2KNG and <a href="https://blog.dc7ia.eu">DC7IA</a> all made attempts,
but neither got anything off the air.
SA2KNG provides this transcription based on the audio from SAQ's YouTube livestream:</p>
<div class="highlight"><pre><span></span><code><span class="nv">cq</span><span class="w"> </span><span class="nv">de …</span></code></pre></div><p>Just a quick after-the-fact update to the
<a href="http://www.härdin.se/blog/2018/04/25/saq-receiver-in-gnu-radio/">previous post</a>
about trying to receive the Swedish world heritage VLF transmitter SAQ in Varberg.
Me, SA2KNG and <a href="https://blog.dc7ia.eu">DC7IA</a> all made attempts,
but neither got anything off the air.
SA2KNG provides this transcription based on the audio from SAQ's YouTube livestream:</p>
<div class="highlight"><pre><span></span><code><span class="nv">cq</span><span class="w"> </span><span class="nv">de</span><span class="w"> </span><span class="nv">saq</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nv">this</span><span class="w"> </span><span class="nv">is</span><span class="w"> </span><span class="nv">grimeton</span><span class="w"> </span><span class="nv">radio</span><span class="o">/</span><span class="nv">saq</span><span class="w"> </span><span class="nv">in</span><span class="w"> </span><span class="nv">an</span><span class="w"> </span><span class="nv">extra</span><span class="w"> </span><span class="nv">transmission</span><span class="w"> </span><span class="nv">using</span><span class="w"> </span><span class="nv">the</span>
<span class="nv">alexanderson</span><span class="w"> </span><span class="mi">200</span><span class="w"> </span><span class="nv">kw</span><span class="w"> </span><span class="nv">alternator</span><span class="w"> </span><span class="nv">on</span><span class="w"> </span><span class="nv">vlf</span><span class="w"> </span><span class="mi">17</span>.<span class="mi">2</span><span class="w"> </span><span class="nv">khz</span>.<span class="w"> </span><span class="nv">today</span><span class="w"> </span><span class="nv">we</span><span class="w"> </span><span class="nv">celebrate</span><span class="w"> </span><span class="nv">the</span>
<span class="nv">radio</span><span class="w"> </span><span class="nv">staion</span><span class="w"> </span><span class="nv">as</span><span class="w"> </span><span class="nv">part</span><span class="w"> </span><span class="nv">of</span><span class="w"> </span><span class="nv">the</span><span class="w"> </span><span class="nv">day</span><span class="w"> </span><span class="nv">of</span><span class="w"> </span><span class="nv">industrial</span><span class="w"> </span><span class="nv">culture</span><span class="w"> </span><span class="nv">heritage</span>.<span class="w"> </span><span class="nv">we</span><span class="w"> </span><span class="k">do</span><span class="w"> </span><span class="nv">not</span>
<span class="nv">request</span><span class="w"> </span><span class="nv">qsl</span><span class="w"> </span><span class="nv">reports</span><span class="w"> </span><span class="nv">on</span><span class="w"> </span><span class="nv">this</span><span class="w"> </span><span class="nv">transmission</span>.<span class="w"> </span><span class="nv">we</span><span class="w"> </span><span class="nv">also</span><span class="w"> </span><span class="nv">plan</span><span class="w"> </span><span class="nv">to</span><span class="w"> </span><span class="nv">transmit</span><span class="w"> </span><span class="nv">on</span>
<span class="nv">alexanderson</span><span class="w"> </span><span class="nv">day</span><span class="w"> </span><span class="nv">on</span><span class="w"> </span><span class="nv">july</span><span class="w"> </span><span class="mi">1</span><span class="nv">st</span><span class="w"> </span><span class="nv">at</span><span class="w"> </span><span class="mi">09</span>.<span class="mi">00</span><span class="w"> </span><span class="nv">utc</span><span class="w"> </span><span class="nv">and</span><span class="w"> </span><span class="mi">13</span>.<span class="mi">00</span><span class="w"> </span><span class="nv">utc</span>.<span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nv">signed</span><span class="w"> </span><span class="nv">world</span>
<span class="nv">heritage</span><span class="w"> </span><span class="nv">grimeton</span><span class="w"> </span><span class="nv">radio</span><span class="w"> </span><span class="nv">station</span><span class="w"> </span><span class="nv">and</span><span class="w"> </span><span class="nv">the</span><span class="w"> </span><span class="nv">alexander</span><span class="w"> </span><span class="nv">association</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nv">de</span><span class="w"> </span><span class="nv">saq</span><span class="w"> </span><span class="nv">saq</span><span class="w"> </span><span class="nv">saq</span>
</code></pre></div>
<p>I'm working another post about more FreeCAD fiddling, expect that some time later this week.</p>SAQ receiver in GNU Radio2018-04-25T23:28:43+02:002018-04-25T23:28:43+02:00tomastag:www.härdin.se,2018-04-25:/blog/2018/04/25/saq-receiver-in-gnu-radio/<p>Today I spent about two hours messing around in GNU Radio in order to write a
receiver for the <a href="https://en.wikipedia.org/wiki/Grimeton_VLF_transmitter">VLF transmitter in Grimeton, Varberg, Sweden (callsign SAQ)</a>.
The Grimeton transmitter is one of the last of its kind,
and uses a reluctance-based mechanical oscillator known as an
<a href="https://en.wikipedia.org/wiki/Alexanderson_alternator">Alexanderson alternator</a>
to …</p><p>Today I spent about two hours messing around in GNU Radio in order to write a
receiver for the <a href="https://en.wikipedia.org/wiki/Grimeton_VLF_transmitter">VLF transmitter in Grimeton, Varberg, Sweden (callsign SAQ)</a>.
The Grimeton transmitter is one of the last of its kind,
and uses a reluctance-based mechanical oscillator known as an
<a href="https://en.wikipedia.org/wiki/Alexanderson_alternator">Alexanderson alternator</a>
to transmit Morse code (CW in radio jargon).
Because of this the operating frequency of the station is very low: 17.2 kHz.
Since this frequency is in the audio range,
it is quite common for VLF enthusiasts to use some programs and a simple
antenna connected to the microphone jack on their computer or smartphne
to listen whenver SAQ or other VLF stations are broadcasting.</p>
<p>Incidentally,
SAQ is scheduled to transmit on <a href="http://alexander.n.se/saq-on-air-on-may-1st/?lang=en">May 1st 12:00 Swedish time (10:00 UTC)</a> 📻</p>
<h1>Where GNU Radio comes in</h1>
<p>Unless the listener has very young ears (or is a dog),
some form of signal processing must be used to bring the 17.2 kHz down to something
more listenable like 1 kHz.
I decided to use the frequency translating FFT filter block
for this,
bringing the signal down to 0 Hz and filtering out everything outside ±50 Hz of it.
The filtered signal is then mixed up to the desired listening frequency.</p>
<p>You can download a .grc file I wrote that does this by clicking <a href="http://www.härdin.se/files/blog/saq/saq_rx.grc">here</a>.
That said, on to the pictures:</p>
<p><img alt="GNU Radio companion screenshot" src="http://www.härdin.se/files/blog/saq/saq_rx.grc.png" title="GNU Radio companion screenshot"></p>
<p>On the left is the microphone input,
which gets a 15.2 kHz test signal injected.
The combined signal is then mixed down, filtered and mixed up again as described earlier.
Finally the result is converted to a real signal and sent to an audio sink (speakers/headphones).
There are also two FFT blocks for plotting added at the input and output respectively.</p>
<p>Here's a screenshot of the entire thing in action:</p>
<p><img alt="WX GUI" src="http://www.härdin.se/files/blog/saq/saq_rx_gui.png" title="WX GUI"></p>
<p>There are five sliders, which serve the following functions:</p>
<dl>
<dt>transition_width</dt>
<dd>How sharply the filter rolls off, in Hz.</dd>
<dt>test_tone</dt>
<dd>Frequency of the injected test tone, in Hz.</dd>
<dt>output_frequency</dt>
<dd>At what frequency to put the filtered signal, in Hz.</dd>
<dt>gain_db</dt>
<dd>Post-filter amplitude gain, in dB.</dd>
<dt>filter_width</dt>
<dd>The width of the filter, in Hz.</dd>
<dt>center_freq</dt>
<dd>The frequency to receive, in Hz.</dd>
</dl>
<p>Hopefully this will work fine come May 1st,
or some other time later this year.
SAQ typically activates twice per year.</p>
<p><a href="http://www.härdin.se/files/blog/saq/saq_rx.grc">Again, the .grc file for this graph can be downloaded by clicking here</a> 😊</p>
<p>Update: Here is a screenshot of GNU Radio being piped to fldigi for CW decoding,
since I suck at decoding Morse by ear:</p>
<p><img alt="GNU Radio being piped to fldigi" src="http://www.härdin.se/files/blog/saq/gnuradio_fldigi.png" title="GNU Radio being piped to fldigi"></p>
<p>I made use of pulse_monitor as the capture device for PortAudio in the audio options.
This means fldigi hears whatever is being played through the speakers.</p>Tor onion service up!2018-04-23T20:13:24+02:002018-04-23T20:13:24+02:00tomastag:www.härdin.se,2018-04-23:/blog/2018/04/23/tor-onion-service-up/<p><img alt="Tor poster" src="http://www.härdin.se/images/tor-project-offline.jpg" title="Tor poster"></p>
<p>In my continuing efforts to make this site even more cybre,
I set up a Tor .onion service the other day:
<a href="http://xynphzf7j7newda6.onion/">http://xynphzf7j7newda6.onion/</a>
(you need Tor browser to access it, download it <a href="https://www.torproject.org/download/download-easy.html.en">here</a>)</p>Solar panel source drop2018-04-23T11:24:29+02:002018-04-23T11:24:29+02:00tomastag:www.härdin.se,2018-04-23:/blog/2018/04/23/solar-panel-source-drop/<p>I put the source code for the previous FreeCAD / solar power articles
(<a href="http://www.härdin.se/blog/2018/01/28/trying-out-freecad/">1</a>,
<a href="http://www.härdin.se/blog/2018/02/08/freecad-follow-up/">2</a>,
<a href="http://www.härdin.se/blog/2018/03/10/triangular-solar-panel-mount/">3</a>,
<a href="http://www.härdin.se/blog/2018/03/17/triangular-solar-panel-mount-version-2/">4</a>)
up on <a href="https://github.com/Tjoppen/solar_stuff">GitHub</a>.
Alternatively you can download it in .zip form by clicking <a href="http://www.härdin.se/files/blog/solar_stuff.zip">here</a>.</p>Triangular solar panel mount version 22018-03-17T21:20:46+01:002018-03-17T21:20:46+01:00tomastag:www.härdin.se,2018-03-17:/blog/2018/03/17/triangular-solar-panel-mount-version-2/<p>Yet another stab at the fabled solar panel mount.
Major differences from last time are moving the pivot forward,
adding a way to pin the adjustment bar to the bottom bar when the array is in the lowest/summer position (hence the second, rear hole),
and mating the adjustment bar …</p><p>Yet another stab at the fabled solar panel mount.
Major differences from last time are moving the pivot forward,
adding a way to pin the adjustment bar to the bottom bar when the array is in the lowest/summer position (hence the second, rear hole),
and mating the adjustment bar with the center of the panels rather than below them.
Hopefully this makes the torque at the top hinge much lower.</p>
<p><img alt="The modified mount" src="http://www.härdin.se/images/tri_mount_v2.png"></p>Triangular solar panel mount2018-03-10T21:36:28+01:002018-03-10T21:36:28+01:00tomastag:www.härdin.se,2018-03-10:/blog/2018/03/10/triangular-solar-panel-mount/<p>More paper sketching and FreeCAD fiddling has yielded a triangular solar panel mount.
A 3D rendering of the current design can be seen below:</p>
<p><img alt="The mount in question" src="http://www.härdin.se/images/tri_mount.png"></p>
<p>Benefits of this design include the hinge being close to the ground, simplifying construction/mounting.
A triangle is also stronger than a square, removing the need …</p><p>More paper sketching and FreeCAD fiddling has yielded a triangular solar panel mount.
A 3D rendering of the current design can be seen below:</p>
<p><img alt="The mount in question" src="http://www.härdin.se/images/tri_mount.png"></p>
<p>Benefits of this design include the hinge being close to the ground, simplifying construction/mounting.
A triangle is also stronger than a square, removing the need for cross beams.
The hinge is now a simple pin or M20 screw + nut.</p>
<p>This design uses 2x6" lumber, since 2x4" felt a bit anemic in the long run and 2x5" isn't much cheaper.
2x7" and above is another price jump.</p>
<p>Potential changes include making the base of the triangular frame a bit wider.</p>
<p>edit: Like the previous post, here's a screenshot of the design of the adjustment bar (click for a larger view):</p>
<p><a href="http://www.härdin.se/images/tri_mount_trig.png"><img alt="Lots of lines and constraints" src="http://www.härdin.se/images/tri_mount_trig_thumb.png"></a></p>Custom CSS2018-03-08T22:39:07+01:002018-03-08T22:39:07+01:00tomastag:www.härdin.se,2018-03-08:/blog/2018/03/08/custom-css/<p>I decided to modify/simplify the CSS on this thing to something more <em>~cybre~</em>.
Makes the place feel more-- comfy.
Colors are probably not final - enjoy the green/red on dark gray for now.
The only thing that really remains of the old theme is the category selector ^^ further up …</p><p>I decided to modify/simplify the CSS on this thing to something more <em>~cybre~</em>.
Makes the place feel more-- comfy.
Colors are probably not final - enjoy the green/red on dark gray for now.
The only thing that really remains of the old theme is the category selector ^^ further up ^^ just below the page title.
The old theme was "notmyidea" by <a href="http://coding.smashingmagazine.com/2009/08/04/designing-a-html-5-layout-from-scratch/">Smashing Magazine</a>.
A side effect of this is that the HTML is now even smaller, at 14 KiB for the blog index.</p>FreeCAD follow-up2018-02-08T21:20:36+01:002018-02-08T21:20:36+01:00tomastag:www.härdin.se,2018-02-08:/blog/2018/02/08/freecad-follow-up/<p>More progress on the solar panel mount has been made.
I have been poking more with FreeCAD,
in addition to getting greenlit by the municipality.
Mounts such as this one don't count as "buildings", so no permit is required.</p>
<p>I redid the previous drawing to use 45x295 and 24x120 lumber …</p><p>More progress on the solar panel mount has been made.
I have been poking more with FreeCAD,
in addition to getting greenlit by the municipality.
Mounts such as this one don't count as "buildings", so no permit is required.</p>
<p>I redid the previous drawing to use 45x295 and 24x120 lumber,
added some faux solar panels based on Chinese measurements
and made a rather involved drawing for figuring out where the holes in the angle adjustment bar should go.
Before I go into detail on the latter, here's a picture that gives an overview of the "business end" of the mount:</p>
<p><img alt="3-D rendering" src="http://www.härdin.se/images/stag-3d.png"></p>
<p>It's not entirely finished; there's still some brackets to be designed that go on the panels which the adjustment bar mounts to and can swing inside.</p>
<p>A rather crowded screenshot of the adjustment bar sketch can be seen below:</p>
<p><img alt="2-D drawing" src="http://www.härdin.se/images/stag-2d.png"></p>
<p>This is for three angles: 45°, 77.5° and 90°.
Relevant measurements are how far up and back the panel side swing mount is (topmost hole, 600 mm up and 150 mm back),
and where the horizontal support hole that the adjustment bar mounts into should go (700 mm back).
The rest of the drawing is related to figuring out how far from the swing hole the other 40 mm holes should go.
Adding a couple more holes isn't terribly hard, but this drawing shows that the positions of the holes along the bar
correspond to the angles linearly enough for eyeballing the reset.</p>
<p>I'm better able to deal with FreeCAD's quirks now, but the inability to specify assembly constraints is still a huge pain.
Hopefully 0.17 is released soonish, else I will simply be forced to compile my own.</p>Trying out FreeCAD2018-01-28T23:04:57+01:002018-01-28T23:04:57+01:00tomastag:www.härdin.se,2018-01-28:/blog/2018/01/28/trying-out-freecad/<p>This week's Sunday project was to try and draw a structure whose purpose is to get some solar panels ~1.5 meters off the ground.
I have ordered ten 270 Watt modules which will be arriving in spring and plan on building a structure to mount them in which can …</p><p>This week's Sunday project was to try and draw a structure whose purpose is to get some solar panels ~1.5 meters off the ground.
I have ordered ten 270 Watt modules which will be arriving in spring and plan on building a structure to mount them in which can be
tilted at least on a per-season basis.
The main goal is to be able to have the panels vertical during winter, both to catch as much sunlight as possible and to keep snow off.
Snow is also the reason for the 1.5 meter elevation.</p>
<p>For this I decided to give FreeCAD a try.
The following picture is what I came up with:</p>
<p><a href="http://www.härdin.se/images/solar_mount.png"><img alt="FreeCAD screenshot of how far I got with the structure in around two hours" src="http://www.härdin.se/images/solar_mount2.png"></a></p>
<p>This is far from finished, and more of a learning experience really.
The entire construction is 45x95 mm lumber (2" x 4"), which is way too small.
A reference design that a friend of mine sent me uses 45x195 mm for long horizontal parts and 45x120 for vertical and diagonal bits.
I have some lumber stashed away too that I will have to measure come spring,
much of which are quite hefty pieces.</p>
<p>I found the following tutorials on YouTube useful:</p>
<ul>
<li><a href="http://youtu.be/lfinO3EGXeo">Placing Parts in FreeCAD</a></li>
<li><a href="http://www.youtube.com/watch?v=08aFSivE3L8">FreeCAD Lesson 11 - Bird Feeder</a></li>
</ul>
<p>The main problem/concern I had when making this is the lack of an assembly workbench in FreeCAD 0.16.
In other words being able to specify how parts go together with constraints similar to how parts are designed with constraints.
This is something which is in the works for future versions,
but I didn't feel like compiling my own binaries just to get that.
For now this leads to some annoyance when parts have to be repositioned if dimensions are changed.
Therefore it is currently easier to draft something on paper and only use FreeCAD for veryfying that it fits together in 3D,
and for sanity checking measurements.</p>Trying out Ada SPARK2018-01-20T20:34:00+01:002018-01-20T20:34:00+01:00tomastag:www.härdin.se,2018-01-20:/blog/2018/01/20/trying-out-ada-spark/<p>Lately me and <a href="http://www.nauck.se/">Benjamin Nauck</a> have been investigating languages with proving functionality,
such as the variant of <a href="https://en.wikipedia.org/wiki/Ada_(programming_language)">Ada</a> known as <a href="https://en.wikipedia.org/wiki/SPARK_(programming_language)">SPARK</a>.
The basic idea of such languages is that the programmer can supply a set of contracts on the inputs and outputs of each function,
and then a prover (gnatprove …</p><p>Lately me and <a href="http://www.nauck.se/">Benjamin Nauck</a> have been investigating languages with proving functionality,
such as the variant of <a href="https://en.wikipedia.org/wiki/Ada_(programming_language)">Ada</a> known as <a href="https://en.wikipedia.org/wiki/SPARK_(programming_language)">SPARK</a>.
The basic idea of such languages is that the programmer can supply a set of contracts on the inputs and outputs of each function,
and then a prover (gnatprove) is run on the program which checks that the contracts are indeed fulfilled for every possible combination of inputs.
This is great for catching lots of bugs, for example issues due to overflow or when math functions are given atypical floating points numbers like ∞ or NaN (not-a-number).
By comparison languages such as C or C++ are not able to provide guarantees like these, not even current popular "safe" languages like Rust or Go.
<em>Update: there are some inaccuracies in this post, see <a href="#comments">the comments section</a>.</em></p>
<p>I decided to make a Saturday project out of writing a primality tester and integer square root function in Ada, then throwing some SPARK contracts on top of them.
Both the primality testing (IsPrime) and integer square root functions (Isqrt and Isqrt2) are limited by the maximum range of Integer in Ada: 2147483647.
This also happens to be a Mersenne prime.
IsPrime does typical trial division up to the square root of the input value.
Integer square roots are done because Sqrt in Ada.Numerics.Elementary_Functions gives no guarantees on the returned values beyond them being >= 0.
gnatprove also has trouble proving that if some integer x is >= 5 then Float(x) >= 5.0.
For these reasons I decided to implement my own square root function.</p>
<p>I decided to write two integer square root implementations.
The first implementation (Isqrt) iterates i from 2 .. 46340 (floor(sqrt(2147483647))) and checks at every step if i² >= num and returns either i or i-1 if that is the case.
This is of course very slow, but fairly easy to prove correct.
The key to proving this was the Loop_Invariant pragma.
Isqrt is listed below:</p>
<div class="highlight"><pre><span></span><code> <span class="c1">-- Returns floor(sqrt(num)) for 0 <= num <= 2147483647 (Natural'Last)</span>
<span class="kd">function</span> <span class="nf">Isqrt</span> <span class="p">(</span><span class="nv">num</span> <span class="p">: </span><span class="nv">Natural</span><span class="p">)</span> <span class="kr">return</span> <span class="kt">Natural</span> <span class="kn">with</span>
<span class="n">SPARK_Mode</span> <span class="p">=></span> <span class="n">On</span><span class="p">,</span>
<span class="n">Post</span> <span class="p">=></span>
<span class="p">(</span><span class="kr">if</span> <span class="n">num</span> <span class="o"><</span> <span class="mi">46340</span><span class="o">*</span><span class="mi">46340</span> <span class="kr">then</span>
<span class="n">num</span> <span class="ow">in</span> <span class="n">Isqrt</span><span class="p">'</span><span class="na">Result</span><span class="o">**</span><span class="mi">2</span> <span class="p">..</span> <span class="p">(</span><span class="n">Isqrt</span><span class="p">'</span><span class="na">Result</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span><span class="o">**</span><span class="mi">2</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="ow">and then</span> <span class="p">(</span><span class="kr">if</span> <span class="n">num</span> <span class="o">>=</span> <span class="mi">46340</span><span class="o">*</span><span class="mi">46340</span> <span class="kr">then</span> <span class="n">Isqrt</span><span class="p">'</span><span class="na">Result</span> <span class="o">=</span> <span class="mi">46340</span><span class="p">)</span>
<span class="kr">is</span>
<span class="kr">begin</span>
<span class="c1">-- 0 -> 0, 1 -> 1</span>
<span class="kr">if</span> <span class="n">num</span> <span class="o"><</span> <span class="mi">2</span> <span class="kr">then</span>
<span class="kr">return</span> <span class="n">num</span><span class="p">;</span>
<span class="kr">end</span> <span class="kr">if</span><span class="p">;</span>
<span class="kr">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="mi">2</span> <span class="p">..</span> <span class="mi">46340</span> <span class="kr">loop</span>
<span class="kr">if</span> <span class="n">i</span><span class="o">*</span><span class="n">i</span> <span class="o">=</span> <span class="n">num</span> <span class="kr">then</span>
<span class="kr">return</span> <span class="n">i</span><span class="p">;</span>
<span class="kr">end</span> <span class="kr">if</span><span class="p">;</span>
<span class="kr">if</span> <span class="n">i</span><span class="o">*</span><span class="n">i</span> <span class="o">></span> <span class="n">num</span> <span class="kr">then</span>
<span class="kr">return</span> <span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="kr">end</span> <span class="kr">if</span><span class="p">;</span>
<span class="kr">pragma</span> <span class="cp">Loop_Invariant</span><span class="p">(</span><span class="n">i</span><span class="o">*</span><span class="n">i</span> <span class="o"><</span> <span class="n">num</span><span class="p">);</span>
<span class="kr">end</span> <span class="kr">loop</span><span class="p">;</span>
<span class="kr">return</span> <span class="mi">46340</span><span class="p">;</span>
<span class="kr">end</span> <span class="nf">Isqrt</span><span class="p">;</span>
</code></pre></div>
<p>The second integer square root (Isqrt2) computes the value by recursion.
A range is kept and halved at every step until it is known that the solution lies between two consecutive integers.
Then the lowest of those two integers is returned.
This variant turned out to be easier to write.
Isqrt2 and the recursive Isqrt2_inner are given below:</p>
<div class="highlight"><pre><span></span><code> <span class="kd">function</span> <span class="nf">Isqrt2_inner</span> <span class="p">(</span><span class="nv">num</span><span class="p">,</span> <span class="nv">lo</span><span class="p">,</span> <span class="nv">hi</span> <span class="p">: </span><span class="nv">Natural</span><span class="p">)</span> <span class="kr">return</span> <span class="kt">Natural</span> <span class="kn">with</span>
<span class="n">SPARK_Mode</span> <span class="p">=></span> <span class="n">On</span><span class="p">,</span>
<span class="n">Pre</span> <span class="p">=></span>
<span class="n">lo</span> <span class="ow">in</span> <span class="mi">1</span> <span class="p">..</span> <span class="mi">46340</span> <span class="ow">and then</span>
<span class="n">hi</span> <span class="ow">in</span> <span class="mi">1</span> <span class="p">..</span> <span class="mi">46340</span> <span class="ow">and then</span>
<span class="n">lo</span> <span class="o"><</span> <span class="n">hi</span> <span class="ow">and then</span>
<span class="n">num</span> <span class="ow">in</span> <span class="n">lo</span><span class="o">**</span><span class="mi">2</span> <span class="p">..</span> <span class="n">hi</span><span class="o">**</span><span class="mi">2</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span>
<span class="n">Post</span> <span class="p">=></span>
<span class="n">num</span> <span class="ow">in</span> <span class="n">Isqrt2_inner</span><span class="p">'</span><span class="na">Result</span><span class="o">**</span><span class="mi">2</span> <span class="p">..</span> <span class="p">(</span><span class="n">Isqrt2_inner</span><span class="p">'</span><span class="na">Result</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span><span class="o">**</span><span class="mi">2</span> <span class="o">-</span> <span class="mi">1</span>
<span class="kr">is</span>
<span class="n">mid</span> <span class="p">:</span> <span class="kt">Natural</span><span class="p">;</span>
<span class="kr">begin</span>
<span class="kr">if</span> <span class="n">lo</span> <span class="o">=</span> <span class="n">hi</span><span class="o">-</span><span class="mi">1</span> <span class="kr">then</span>
<span class="kr">return</span> <span class="n">lo</span><span class="p">;</span>
<span class="kr">end</span> <span class="kr">if</span><span class="p">;</span>
<span class="n">mid</span> <span class="p">:=</span> <span class="p">(</span><span class="n">lo</span> <span class="o">+</span> <span class="n">hi</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span>
<span class="kr">pragma</span> <span class="cp">Assert</span> <span class="p">(</span><span class="n">mid</span> <span class="ow">in</span> <span class="n">lo</span><span class="o">+</span><span class="mi">1</span> <span class="p">..</span> <span class="n">hi</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="kr">if</span> <span class="n">mid</span><span class="o">**</span><span class="mi">2</span> <span class="o">></span> <span class="n">num</span> <span class="kr">then</span>
<span class="kr">return</span> <span class="n">Isqrt2_inner</span><span class="p">(</span><span class="n">num</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">mid</span><span class="p">);</span>
<span class="kr">else</span>
<span class="kr">return</span> <span class="n">Isqrt2_inner</span><span class="p">(</span><span class="n">num</span><span class="p">,</span> <span class="n">mid</span><span class="p">,</span> <span class="n">hi</span><span class="p">);</span>
<span class="kr">end</span> <span class="kr">if</span><span class="p">;</span>
<span class="kr">end</span> <span class="nf">Isqrt2_inner</span><span class="p">;</span>
<span class="c1">-- Faster, recursive version of Isqrt</span>
<span class="kd">function</span> <span class="nf">Isqrt2</span> <span class="p">(</span><span class="nv">num</span> <span class="p">: </span><span class="nv">Natural</span><span class="p">)</span> <span class="kr">return</span> <span class="kt">Natural</span> <span class="kn">with</span>
<span class="n">SPARK_Mode</span> <span class="p">=></span> <span class="n">On</span><span class="p">,</span>
<span class="n">Post</span> <span class="p">=></span>
<span class="p">(</span><span class="kr">if</span> <span class="n">num</span> <span class="o"><</span> <span class="mi">46340</span><span class="o">*</span><span class="mi">46340</span> <span class="kr">then</span>
<span class="n">Isqrt2</span><span class="p">'</span><span class="na">Result</span> <span class="o"><</span> <span class="mi">46340</span> <span class="ow">and then</span>
<span class="n">num</span> <span class="ow">in</span> <span class="n">Isqrt2</span><span class="p">'</span><span class="na">Result</span><span class="o">**</span><span class="mi">2</span> <span class="p">..</span> <span class="p">(</span><span class="n">Isqrt2</span><span class="p">'</span><span class="na">Result</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span><span class="o">**</span><span class="mi">2</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="ow">and then</span> <span class="p">(</span><span class="kr">if</span> <span class="n">num</span> <span class="o">>=</span> <span class="mi">46340</span><span class="o">*</span><span class="mi">46340</span> <span class="kr">then</span> <span class="n">Isqrt2</span><span class="p">'</span><span class="na">Result</span> <span class="o">=</span> <span class="mi">46340</span><span class="p">)</span>
<span class="kr">is</span>
<span class="kr">begin</span>
<span class="c1">-- 0 -> 0, 1 -> 1</span>
<span class="kr">if</span> <span class="n">num</span> <span class="o"><</span> <span class="mi">2</span> <span class="kr">then</span>
<span class="kr">return</span> <span class="n">num</span><span class="p">;</span>
<span class="kr">end</span> <span class="kr">if</span><span class="p">;</span>
<span class="kr">if</span> <span class="n">num</span> <span class="o">>=</span> <span class="mi">46340</span><span class="o">*</span><span class="mi">46340</span> <span class="kr">then</span>
<span class="kr">return</span> <span class="mi">46340</span><span class="p">;</span>
<span class="kr">end</span> <span class="kr">if</span><span class="p">;</span>
<span class="kr">return</span> <span class="n">Isqrt2_inner</span><span class="p">(</span><span class="n">num</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">46340</span><span class="p">);</span>
<span class="kr">end</span> <span class="nf">Isqrt2</span><span class="p">;</span>
</code></pre></div>
<p>IsPrime itself is not very interesting.
I don't prove that the function actually behaves correctly,
such a proof would be very involved.
All we can know is that it will terminate and that its assertions are correct.</p>
<p>The complete code listing will be given below.
There are three files: isprime.adb which has the bulk of the code, isprime.ads is like a header, and main.adb which does user interaction:</p>
<div class="highlight"><pre><span></span><code><span class="c1">-- isprime.adb</span>
<span class="kd">package</span> <span class="kd">body</span> <span class="kr">Is</span><span class="n">Prime</span> <span class="kr">is</span>
<span class="c1">-- Returns floor(sqrt(num)) for 0 <= num <= 2147483647 (Natural'Last)</span>
<span class="kd">function</span> <span class="nf">Isqrt</span> <span class="p">(</span><span class="nv">num</span> <span class="p">: </span><span class="nv">Natural</span><span class="p">)</span> <span class="kr">return</span> <span class="kt">Natural</span> <span class="kn">with</span>
<span class="n">SPARK_Mode</span> <span class="p">=></span> <span class="n">On</span><span class="p">,</span>
<span class="n">Post</span> <span class="p">=></span>
<span class="p">(</span><span class="kr">if</span> <span class="n">num</span> <span class="o"><</span> <span class="mi">46340</span><span class="o">*</span><span class="mi">46340</span> <span class="kr">then</span>
<span class="n">num</span> <span class="ow">in</span> <span class="n">Isqrt</span><span class="p">'</span><span class="na">Result</span><span class="o">**</span><span class="mi">2</span> <span class="p">..</span> <span class="p">(</span><span class="n">Isqrt</span><span class="p">'</span><span class="na">Result</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span><span class="o">**</span><span class="mi">2</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="ow">and then</span> <span class="p">(</span><span class="kr">if</span> <span class="n">num</span> <span class="o">>=</span> <span class="mi">46340</span><span class="o">*</span><span class="mi">46340</span> <span class="kr">then</span> <span class="n">Isqrt</span><span class="p">'</span><span class="na">Result</span> <span class="o">=</span> <span class="mi">46340</span><span class="p">)</span>
<span class="kr">is</span>
<span class="kr">begin</span>
<span class="c1">-- 0 -> 0, 1 -> 1</span>
<span class="kr">if</span> <span class="n">num</span> <span class="o"><</span> <span class="mi">2</span> <span class="kr">then</span>
<span class="kr">return</span> <span class="n">num</span><span class="p">;</span>
<span class="kr">end</span> <span class="kr">if</span><span class="p">;</span>
<span class="kr">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="mi">2</span> <span class="p">..</span> <span class="mi">46340</span> <span class="kr">loop</span>
<span class="kr">if</span> <span class="n">i</span><span class="o">*</span><span class="n">i</span> <span class="o">=</span> <span class="n">num</span> <span class="kr">then</span>
<span class="kr">return</span> <span class="n">i</span><span class="p">;</span>
<span class="kr">end</span> <span class="kr">if</span><span class="p">;</span>
<span class="kr">if</span> <span class="n">i</span><span class="o">*</span><span class="n">i</span> <span class="o">></span> <span class="n">num</span> <span class="kr">then</span>
<span class="kr">return</span> <span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="kr">end</span> <span class="kr">if</span><span class="p">;</span>
<span class="kr">pragma</span> <span class="cp">Loop_Invariant</span><span class="p">(</span><span class="n">i</span><span class="o">*</span><span class="n">i</span> <span class="o"><</span> <span class="n">num</span><span class="p">);</span>
<span class="kr">end</span> <span class="kr">loop</span><span class="p">;</span>
<span class="kr">return</span> <span class="mi">46340</span><span class="p">;</span>
<span class="kr">end</span> <span class="nf">Isqrt</span><span class="p">;</span>
<span class="kd">function</span> <span class="nf">Isqrt2_inner</span> <span class="p">(</span><span class="nv">num</span><span class="p">,</span> <span class="nv">lo</span><span class="p">,</span> <span class="nv">hi</span> <span class="p">: </span><span class="nv">Natural</span><span class="p">)</span> <span class="kr">return</span> <span class="kt">Natural</span> <span class="kn">with</span>
<span class="n">SPARK_Mode</span> <span class="p">=></span> <span class="n">On</span><span class="p">,</span>
<span class="n">Pre</span> <span class="p">=></span>
<span class="n">lo</span> <span class="ow">in</span> <span class="mi">1</span> <span class="p">..</span> <span class="mi">46340</span> <span class="ow">and then</span>
<span class="n">hi</span> <span class="ow">in</span> <span class="mi">1</span> <span class="p">..</span> <span class="mi">46340</span> <span class="ow">and then</span>
<span class="n">lo</span> <span class="o"><</span> <span class="n">hi</span> <span class="ow">and then</span>
<span class="n">num</span> <span class="ow">in</span> <span class="n">lo</span><span class="o">**</span><span class="mi">2</span> <span class="p">..</span> <span class="n">hi</span><span class="o">**</span><span class="mi">2</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span>
<span class="n">Post</span> <span class="p">=></span>
<span class="n">num</span> <span class="ow">in</span> <span class="n">Isqrt2_inner</span><span class="p">'</span><span class="na">Result</span><span class="o">**</span><span class="mi">2</span> <span class="p">..</span> <span class="p">(</span><span class="n">Isqrt2_inner</span><span class="p">'</span><span class="na">Result</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span><span class="o">**</span><span class="mi">2</span> <span class="o">-</span> <span class="mi">1</span>
<span class="kr">is</span>
<span class="n">mid</span> <span class="p">:</span> <span class="kt">Natural</span><span class="p">;</span>
<span class="kr">begin</span>
<span class="kr">if</span> <span class="n">lo</span> <span class="o">=</span> <span class="n">hi</span><span class="o">-</span><span class="mi">1</span> <span class="kr">then</span>
<span class="kr">return</span> <span class="n">lo</span><span class="p">;</span>
<span class="kr">end</span> <span class="kr">if</span><span class="p">;</span>
<span class="n">mid</span> <span class="p">:=</span> <span class="p">(</span><span class="n">lo</span> <span class="o">+</span> <span class="n">hi</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span>
<span class="kr">pragma</span> <span class="cp">Assert</span> <span class="p">(</span><span class="n">mid</span> <span class="ow">in</span> <span class="n">lo</span><span class="o">+</span><span class="mi">1</span> <span class="p">..</span> <span class="n">hi</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="kr">if</span> <span class="n">mid</span><span class="o">**</span><span class="mi">2</span> <span class="o">></span> <span class="n">num</span> <span class="kr">then</span>
<span class="kr">return</span> <span class="n">Isqrt2_inner</span><span class="p">(</span><span class="n">num</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">mid</span><span class="p">);</span>
<span class="kr">else</span>
<span class="kr">return</span> <span class="n">Isqrt2_inner</span><span class="p">(</span><span class="n">num</span><span class="p">,</span> <span class="n">mid</span><span class="p">,</span> <span class="n">hi</span><span class="p">);</span>
<span class="kr">end</span> <span class="kr">if</span><span class="p">;</span>
<span class="kr">end</span> <span class="nf">Isqrt2_inner</span><span class="p">;</span>
<span class="c1">-- Faster, recursive version of Isqrt</span>
<span class="kd">function</span> <span class="nf">Isqrt2</span> <span class="p">(</span><span class="nv">num</span> <span class="p">: </span><span class="nv">Natural</span><span class="p">)</span> <span class="kr">return</span> <span class="kt">Natural</span> <span class="kn">with</span>
<span class="n">SPARK_Mode</span> <span class="p">=></span> <span class="n">On</span><span class="p">,</span>
<span class="n">Post</span> <span class="p">=></span>
<span class="p">(</span><span class="kr">if</span> <span class="n">num</span> <span class="o"><</span> <span class="mi">46340</span><span class="o">*</span><span class="mi">46340</span> <span class="kr">then</span>
<span class="n">Isqrt2</span><span class="p">'</span><span class="na">Result</span> <span class="o"><</span> <span class="mi">46340</span> <span class="ow">and then</span>
<span class="n">num</span> <span class="ow">in</span> <span class="n">Isqrt2</span><span class="p">'</span><span class="na">Result</span><span class="o">**</span><span class="mi">2</span> <span class="p">..</span> <span class="p">(</span><span class="n">Isqrt2</span><span class="p">'</span><span class="na">Result</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span><span class="o">**</span><span class="mi">2</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="ow">and then</span> <span class="p">(</span><span class="kr">if</span> <span class="n">num</span> <span class="o">>=</span> <span class="mi">46340</span><span class="o">*</span><span class="mi">46340</span> <span class="kr">then</span> <span class="n">Isqrt2</span><span class="p">'</span><span class="na">Result</span> <span class="o">=</span> <span class="mi">46340</span><span class="p">)</span>
<span class="kr">is</span>
<span class="kr">begin</span>
<span class="c1">-- 0 -> 0, 1 -> 1</span>
<span class="kr">if</span> <span class="n">num</span> <span class="o"><</span> <span class="mi">2</span> <span class="kr">then</span>
<span class="kr">return</span> <span class="n">num</span><span class="p">;</span>
<span class="kr">end</span> <span class="kr">if</span><span class="p">;</span>
<span class="kr">if</span> <span class="n">num</span> <span class="o">>=</span> <span class="mi">46340</span><span class="o">*</span><span class="mi">46340</span> <span class="kr">then</span>
<span class="kr">return</span> <span class="mi">46340</span><span class="p">;</span>
<span class="kr">end</span> <span class="kr">if</span><span class="p">;</span>
<span class="kr">return</span> <span class="n">Isqrt2_inner</span><span class="p">(</span><span class="n">num</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">46340</span><span class="p">);</span>
<span class="kr">end</span> <span class="nf">Isqrt2</span><span class="p">;</span>
<span class="c1">-- Tests whether a Positive is prime</span>
<span class="kd">function</span> <span class="nf">IsPrime</span> <span class="p">(</span><span class="nv">num</span> <span class="p">: </span><span class="nv">Positive</span><span class="p">)</span> <span class="kr">return</span> <span class="kt">Boolean</span> <span class="kn">with</span>
<span class="n">SPARK_Mode</span> <span class="p">=></span> <span class="n">On</span>
<span class="kr">is</span>
<span class="n">top</span> <span class="p">:</span> <span class="kt">Positive</span><span class="p">;</span>
<span class="kr">begin</span>
<span class="kr">if</span> <span class="n">num</span> <span class="o">=</span> <span class="mi">2</span> <span class="kr">or</span> <span class="n">num</span> <span class="o">=</span> <span class="mi">3</span> <span class="kr">then</span>
<span class="kr">return</span> <span class="kc">True</span><span class="p">;</span>
<span class="kr">end</span> <span class="kr">if</span><span class="p">;</span>
<span class="kr">if</span> <span class="n">num</span> <span class="ow">mod</span> <span class="mi">2</span> <span class="o">=</span> <span class="mi">0</span> <span class="kr">then</span>
<span class="kr">return</span> <span class="kc">False</span><span class="p">;</span>
<span class="kr">end</span> <span class="kr">if</span><span class="p">;</span>
<span class="n">top</span> <span class="p">:=</span> <span class="n">Isqrt2</span><span class="p">(</span><span class="n">num</span><span class="p">);</span>
<span class="kr">pragma</span> <span class="cp">Assert</span> <span class="p">(</span><span class="n">top</span> <span class="o"><</span> <span class="n">num</span><span class="p">);</span>
<span class="kr">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="kt">Integer</span> <span class="kr">range</span> <span class="mi">3</span> <span class="p">..</span> <span class="n">top</span> <span class="kr">loop</span>
<span class="kr">pragma</span> <span class="cp">Assert</span> <span class="p">(</span><span class="n">i</span> <span class="o"><</span> <span class="n">num</span><span class="p">);</span>
<span class="kr">if</span> <span class="n">num</span> <span class="ow">mod</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span> <span class="kr">then</span>
<span class="kr">return</span> <span class="kc">False</span><span class="p">;</span>
<span class="kr">end</span> <span class="kr">if</span><span class="p">;</span>
<span class="kr">end</span> <span class="kr">loop</span><span class="p">;</span>
<span class="kr">return</span> <span class="kc">True</span><span class="p">;</span>
<span class="kr">end</span> <span class="nf">IsPrime</span><span class="p">;</span>
<span class="kr">end</span> <span class="nf">IsPrime</span><span class="p">;</span>
</code></pre></div>
<div class="highlight"><pre><span></span><code><span class="c1">-- isprime.ads</span>
<span class="kd">package</span> <span class="kr">Is</span><span class="n">Prime</span> <span class="kr">is</span>
<span class="kd">function</span> <span class="nf">IsPrime</span> <span class="p">(</span><span class="nv">num</span> <span class="p">: </span><span class="nv">Positive</span><span class="p">)</span> <span class="kr">return</span> <span class="kt">Boolean</span> <span class="kn">with</span>
<span class="n">SPARK_Mode</span> <span class="p">=></span> <span class="n">On</span><span class="p">,</span>
<span class="n">Pre</span> <span class="p">=></span> <span class="n">num</span> <span class="o">>=</span> <span class="mi">2</span><span class="p">;</span>
<span class="kr">end</span> <span class="nf">IsPrime</span><span class="p">;</span>
</code></pre></div>
<div class="highlight"><pre><span></span><code><span class="c1">-- main.adb</span>
<span class="kn">with</span> <span class="n">Ada.Text_IO</span><span class="p">;</span>
<span class="kn">with</span> <span class="n">Ada.Integer_Text_IO</span><span class="p">;</span>
<span class="kn">with</span> <span class="n">IsPrime</span><span class="p">;</span>
<span class="kd">procedure</span> <span class="nf">Main</span>
<span class="kr">is</span>
<span class="n">num</span> <span class="p">:</span> <span class="kt">Integer</span><span class="p">;</span>
<span class="kr">begin</span>
<span class="n">Ada</span><span class="p">.</span><span class="n">Text_IO</span><span class="p">.</span><span class="n">Put_Line</span><span class="p">(</span><span class="s">"Enter an integer to test"</span><span class="p">);</span>
<span class="n">Ada</span><span class="p">.</span><span class="n">Integer_Text_IO</span><span class="p">.</span><span class="n">Get</span><span class="p">(</span><span class="n">num</span><span class="p">);</span>
<span class="c1">--num := 2147483647; -- largest Positive, also a prime</span>
<span class="kr">if</span> <span class="n">num</span> <span class="o"><</span> <span class="mi">2</span> <span class="kr">then</span>
<span class="n">Ada</span><span class="p">.</span><span class="n">Text_IO</span><span class="p">.</span><span class="n">Put_Line</span><span class="p">(</span><span class="s">"Number must be >= 2"</span><span class="p">);</span>
<span class="kr">return</span><span class="p">;</span>
<span class="kr">end</span> <span class="kr">if</span><span class="p">;</span>
<span class="n">Ada</span><span class="p">.</span><span class="n">Text_IO</span><span class="p">.</span><span class="n">Put_Line</span><span class="p">(</span><span class="kt">Boolean</span><span class="p">'</span><span class="na">Image</span><span class="p">(</span><span class="n">IsPrime</span><span class="p">.</span><span class="n">IsPrime</span><span class="p">(</span><span class="n">num</span><span class="p">)));</span>
<span class="kr">end</span> <span class="nf">Main</span><span class="p">;</span>
</code></pre></div>
<p>Example gnatprove output on the entire project:</p>
<div class="highlight"><pre><span></span><code>gnatprove -P/home/thardin/projects/ada/exempel/default.gpr --level=0 --ide-progress-bar -U
Phase 1 of 2: generation of Global contracts ...
Phase 2 of 2: flow analysis and proof ...
Summary logged in /home/thardin/projects/ada/exempel/obj/gnatprove/gnatprove.out
[2018-01-20 21:24:42] process terminated successfully, elapsed time: 05.20s
</code></pre></div>
<p>Report:</p>
<div class="highlight"><pre><span></span><code><span class="gh">Summary of SPARK analysis</span>
<span class="gh">=========================</span>
<span class="gh">--------------------------------------------------------------------------------------------------------</span>
<span class="gh">SPARK Analysis results Total Flow Interval CodePeer Provers Justified Unproved</span>
<span class="gh">--------------------------------------------------------------------------------------------------------</span>
Data Dependencies . . . . . . .
Flow Dependencies . . . . . . .
Initialization 6 6 . . . . .
Non-Aliasing . . . . . . .
Run-time Checks 26 . . . 26 (CVC4) . .
Assertions 5 . . . 5 (CVC4) . .
Functional Contracts 6 . . . 6 (CVC4) . .
<span class="gh">LSP Verification . . . . . . .</span>
<span class="gh">--------------------------------------------------------------------------------------------------------</span>
Total 43 6 (14%) . . 37 (86%) . .
Analyzed 2 units
in unit isprime, 4 subprograms and packages out of 4 analyzed
IsPrime.IsPrime at isprime.ads:3 flow analyzed (0 errors and 0 warnings) and proved (6 checks)
IsPrime.Isqrt at isprime.adb:3 flow analyzed (0 errors and 0 warnings) and proved (10 checks)
IsPrime.Isqrt2 at isprime.adb:55 flow analyzed (0 errors and 0 warnings) and proved (6 checks)
IsPrime.Isqrt2_inner at isprime.adb:30 flow analyzed (0 errors and 0 warnings) and proved (15 checks)
in unit main, 0 subprograms and packages out of 1 analyzed
Main at main.adb:5 skipped
</code></pre></div>
<p>I tried to prove that Main behaves correctly, but unfortunaly the Text_IO functions do not provide any suitable contracts:</p>
<div class="highlight"><pre><span></span><code><span class="nv">gnatprove</span><span class="w"> </span><span class="o">-</span><span class="nv">P</span><span class="o">/</span><span class="nv">home</span><span class="o">/</span><span class="nv">thardin</span><span class="o">/</span><span class="nv">projects</span><span class="o">/</span><span class="nv">ada</span><span class="o">/</span><span class="nv">exempel</span><span class="o">/</span><span class="nv">default</span>.<span class="nv">gpr</span><span class="w"> </span><span class="o">--</span><span class="nv">ide</span><span class="o">-</span><span class="nv">progress</span><span class="o">-</span><span class="nv">bar</span><span class="w"> </span><span class="o">--</span><span class="nv">level</span><span class="o">=</span><span class="mi">0</span><span class="w"> </span><span class="o">-</span><span class="nv">u</span><span class="w"> </span><span class="nv">main</span>.<span class="nv">adb</span>
<span class="nv">Phase</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="nv">of</span><span class="w"> </span><span class="mi">2</span>:<span class="w"> </span><span class="nv">generation</span><span class="w"> </span><span class="nv">of</span><span class="w"> </span><span class="nv">Global</span><span class="w"> </span><span class="nv">contracts</span><span class="w"> </span>...
<span class="nv">Phase</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="nv">of</span><span class="w"> </span><span class="mi">2</span>:<span class="w"> </span><span class="nv">flow</span><span class="w"> </span><span class="nv">analysis</span><span class="w"> </span><span class="nv">and</span><span class="w"> </span><span class="nv">proof</span><span class="w"> </span>...
<span class="nv">main</span>.<span class="nv">adb</span>:<span class="mi">10</span>:<span class="mi">15</span>:<span class="w"> </span><span class="nv">warning</span>:<span class="w"> </span><span class="nv">no</span><span class="w"> </span><span class="nv">Global</span><span class="w"> </span><span class="nv">contract</span><span class="w"> </span><span class="nv">available</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="s2">"Put_Line"</span>
<span class="nv">main</span>.<span class="nv">adb</span>:<span class="mi">10</span>:<span class="mi">15</span>:<span class="w"> </span><span class="nv">warning</span>:<span class="w"> </span><span class="nv">assuming</span><span class="w"> </span><span class="s2">"Put_Line"</span><span class="w"> </span><span class="nv">has</span><span class="w"> </span><span class="nv">no</span><span class="w"> </span><span class="nv">effect</span><span class="w"> </span><span class="nv">on</span><span class="w"> </span><span class="nv">global</span><span class="w"> </span><span class="nv">items</span>
<span class="nv">main</span>.<span class="nv">adb</span>:<span class="mi">11</span>:<span class="mi">23</span>:<span class="w"> </span><span class="nv">warning</span>:<span class="w"> </span><span class="nv">no</span><span class="w"> </span><span class="nv">Global</span><span class="w"> </span><span class="nv">contract</span><span class="w"> </span><span class="nv">available</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="s2">"Get"</span>
<span class="nv">main</span>.<span class="nv">adb</span>:<span class="mi">11</span>:<span class="mi">23</span>:<span class="w"> </span><span class="nv">warning</span>:<span class="w"> </span><span class="nv">assuming</span><span class="w"> </span><span class="s2">"Get"</span><span class="w"> </span><span class="nv">has</span><span class="w"> </span><span class="nv">no</span><span class="w"> </span><span class="nv">effect</span><span class="w"> </span><span class="nv">on</span><span class="w"> </span><span class="nv">global</span><span class="w"> </span><span class="nv">items</span>
<span class="nv">main</span>.<span class="nv">adb</span>:<span class="mi">15</span>:<span class="mi">18</span>:<span class="w"> </span><span class="nv">warning</span>:<span class="w"> </span><span class="nv">no</span><span class="w"> </span><span class="nv">Global</span><span class="w"> </span><span class="nv">contract</span><span class="w"> </span><span class="nv">available</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="s2">"Put_Line"</span>
<span class="nv">main</span>.<span class="nv">adb</span>:<span class="mi">15</span>:<span class="mi">18</span>:<span class="w"> </span><span class="nv">warning</span>:<span class="w"> </span><span class="nv">assuming</span><span class="w"> </span><span class="s2">"Put_Line"</span><span class="w"> </span><span class="nv">has</span><span class="w"> </span><span class="nv">no</span><span class="w"> </span><span class="nv">effect</span><span class="w"> </span><span class="nv">on</span><span class="w"> </span><span class="nv">global</span><span class="w"> </span><span class="nv">items</span>
<span class="nv">main</span>.<span class="nv">adb</span>:<span class="mi">19</span>:<span class="mi">15</span>:<span class="w"> </span><span class="nv">warning</span>:<span class="w"> </span><span class="nv">no</span><span class="w"> </span><span class="nv">Global</span><span class="w"> </span><span class="nv">contract</span><span class="w"> </span><span class="nv">available</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="s2">"Put_Line"</span>
<span class="nv">main</span>.<span class="nv">adb</span>:<span class="mi">19</span>:<span class="mi">15</span>:<span class="w"> </span><span class="nv">warning</span>:<span class="w"> </span><span class="nv">assuming</span><span class="w"> </span><span class="s2">"Put_Line"</span><span class="w"> </span><span class="nv">has</span><span class="w"> </span><span class="nv">no</span><span class="w"> </span><span class="nv">effect</span><span class="w"> </span><span class="nv">on</span><span class="w"> </span><span class="nv">global</span><span class="w"> </span><span class="nv">items</span>
<span class="nv">Summary</span><span class="w"> </span><span class="nv">logged</span><span class="w"> </span><span class="nv">in</span><span class="w"> </span><span class="o">/</span><span class="nv">home</span><span class="o">/</span><span class="nv">thardin</span><span class="o">/</span><span class="nv">projects</span><span class="o">/</span><span class="nv">ada</span><span class="o">/</span><span class="nv">exempel</span><span class="o">/</span><span class="nv">obj</span><span class="o">/</span><span class="nv">gnatprove</span><span class="o">/</span><span class="nv">gnatprove</span>.<span class="nv">out</span>
[<span class="mi">2018</span><span class="o">-</span><span class="mi">01</span><span class="o">-</span><span class="mi">20</span><span class="w"> </span><span class="mi">21</span>:<span class="mi">26</span>:<span class="mi">37</span>]<span class="w"> </span><span class="nv">process</span><span class="w"> </span><span class="nv">terminated</span><span class="w"> </span><span class="nv">successfully</span>,<span class="w"> </span><span class="nv">elapsed</span><span class="w"> </span><span class="nv">time</span>:<span class="w"> </span><span class="mi">02</span>.<span class="mi">20</span><span class="nv">s</span>
</code></pre></div>
<p><a href="https://stackoverflow.com/questions/47342967/how-to-prove-a-spark-text-io-procedure-precondition-will-hold">This Stackoverflow question</a> seems to indicate that a SPARK.Ada.Text_IO module exists.
Unfortunately I don't have that package in my setup.
<a href="http://docs.adacore.com/sparkdocs-docs/SPARK_Library_UM.htm#_Toc311793153">It was previously known as SPARK_IO</a>, which also does not exist on my machine.</p>
<p>There are however some major limitations with SPARK.
The biggest one is that dynamic memory allocation is not allowed.
All SPARK functions must also terminate.
So SPARK is not suitable for every case at least.
There is however a separation kernel called <a href="https://muen.sk/">Muen</a> which is written in SPARK, so clearly a lot can be done with it.</p>
<p>Finally, I'll mention that there are other tools and languages with similar functionality,
such as <a href="https://en.wikipedia.org/wiki/Coq">Coq</a> and <a href="https://en.wikipedia.org/wiki/Idris_(programming_language)">Idris</a>.
I haven't looked at those yet, but Coq seems especially popular among mathematicians.</p>
<h2 id="comments">Comments</h2>
<p>Piotr Trojanek has this to say,
prompted by <a href="http://www.härdin.se/blog/2018/11/20/trying-out-frama-c/">my future post about Frama-C</a>:</p>
<div class="highlight"><pre><span></span><code><span class="n">Hi</span><span class="w"> </span><span class="n">Tomas</span><span class="p">,</span>
<span class="n">I</span><span class="w"> </span><span class="n">just</span><span class="w"> </span><span class="n">read</span><span class="w"> </span><span class="n">your</span><span class="w"> </span><span class="n">old</span><span class="w"> </span><span class="n">blog</span><span class="w"> </span><span class="n">post</span><span class="w"> </span><span class="s">"Trying out Ada SPARK"</span><span class="p">.</span><span class="w"> </span><span class="n">Thanks</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">describing</span>
<span class="n">your</span><span class="w"> </span><span class="n">experience</span><span class="o">!</span><span class="w"> </span><span class="n">It</span><span class="w"> </span><span class="n">looks</span><span class="w"> </span><span class="n">like</span><span class="w"> </span><span class="n">not</span><span class="w"> </span><span class="n">everything</span><span class="w"> </span><span class="n">went</span><span class="w"> </span><span class="n">well</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="n">your</span><span class="w"> </span><span class="n">trial</span><span class="w"> </span><span class="n">but</span>
<span class="n">perhaps</span><span class="w"> </span><span class="n">I</span><span class="w"> </span><span class="n">could</span><span class="w"> </span><span class="n">clarify</span><span class="w"> </span><span class="n">some</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">issues</span><span class="p">.</span>
<span class="o">*</span><span class="w"> </span><span class="s">"Integer square roots are done because Sqrt in</span>
<span class="w"> </span><span class="n">Ada</span><span class="p">.</span><span class="n">Numerics</span><span class="p">.</span><span class="n">Elementary_Functions</span><span class="w"> </span><span class="n">gives</span><span class="w"> </span><span class="n">no</span><span class="w"> </span><span class="n">guarantees</span><span class="w"> </span><span class="n">on</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">returned</span><span class="w"> </span><span class="n">values</span>
<span class="w"> </span><span class="n">beyond</span><span class="w"> </span><span class="n">them</span><span class="w"> </span><span class="n">being</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="mf">0.</span><span class="s">"</span>
<span class="n">Even</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">SPARK</span><span class="w"> </span><span class="n">would</span><span class="w"> </span><span class="n">exactly</span><span class="w"> </span><span class="n">model</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">guarantees</span><span class="w"> </span><span class="n">provided</span><span class="w"> </span><span class="n">by</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">Ada</span><span class="w"> </span><span class="n">RM</span>
<span class="n">G</span><span class="mf">.2.4</span><span class="p">(</span><span class="mi">6</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="p">.</span><span class="n">e</span><span class="p">.</span><span class="w"> </span><span class="s">"The maximum relative error exhibited by [Sqrt] is 2.0 ·</span>
<span class="n">EF</span><span class="p">.</span><span class="n">Float_Type</span><span class="err">'</span><span class="n">Model_Epsilon</span><span class="s">"), I would still suggest you to stick with</span>
<span class="n">integers</span><span class="p">,</span><span class="w"> </span><span class="n">as</span><span class="w"> </span><span class="n">otherwise</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">easily</span><span class="w"> </span><span class="n">risk</span><span class="w"> </span><span class="n">imprecision</span><span class="p">.</span>
<span class="n">See</span><span class="w"> </span><span class="n">https</span><span class="o">:</span><span class="c1">//en.wikipedia.org/wiki/Floating-point_arithmetic, which says: "Any</span>
<span class="n">integer</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="n">absolute</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="n">less</span><span class="w"> </span><span class="n">than</span><span class="w"> </span><span class="mi">2</span><span class="o">^</span><span class="mi">24</span><span class="w"> </span><span class="n">can</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">exactly</span><span class="w"> </span><span class="n">represented</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">the</span>
<span class="n">single</span><span class="w"> </span><span class="n">precision</span><span class="w"> </span><span class="n">format</span><span class="s">". In particular, the Integer'Last can't be represented</span>
<span class="n">exactly</span><span class="w"> </span><span class="n">as</span><span class="w"> </span><span class="n">Float</span><span class="p">.</span>
<span class="o">*</span><span class="w"> </span><span class="s">"gnatprove also has trouble proving that if some integer x is >= 5 then</span>
<span class="w"> </span><span class="n">Float</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="mf">5.0</span><span class="p">.</span><span class="s">"</span>
<span class="n">Indeed</span><span class="p">,</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="mi">2017</span><span class="w"> </span><span class="n">public</span><span class="w"> </span><span class="n">SPARK</span><span class="w"> </span><span class="k">release</span><span class="w"> </span><span class="n">only</span><span class="w"> </span><span class="n">included</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">alt</span><span class="o">-</span><span class="n">ergo</span><span class="w"> </span><span class="n">solver</span><span class="p">,</span><span class="w"> </span><span class="n">which</span>
<span class="n">isn</span><span class="err">'</span><span class="n">t</span><span class="w"> </span><span class="n">great</span><span class="w"> </span><span class="n">at</span><span class="w"> </span><span class="n">floating</span><span class="o">-</span><span class="n">point</span><span class="w"> </span><span class="n">problems</span><span class="w"> </span><span class="p">(</span><span class="n">you</span><span class="w"> </span><span class="n">could</span><span class="w"> </span><span class="n">add</span><span class="w"> </span><span class="n">other</span><span class="w"> </span><span class="n">solvers</span><span class="w"> </span><span class="n">on</span><span class="w"> </span><span class="n">your</span><span class="w"> </span><span class="n">own</span>
<span class="n">and</span><span class="w"> </span><span class="n">we</span><span class="w"> </span><span class="n">know</span><span class="w"> </span><span class="n">that</span><span class="w"> </span><span class="n">some</span><span class="w"> </span><span class="n">researchers</span><span class="w"> </span><span class="n">did</span><span class="p">).</span><span class="w"> </span><span class="n">The</span><span class="w"> </span><span class="mi">2018</span><span class="w"> </span><span class="k">release</span><span class="w"> </span><span class="n">includes</span><span class="w"> </span><span class="n">also</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">CVC4</span>
<span class="n">solver</span><span class="p">,</span><span class="w"> </span><span class="n">which</span><span class="w"> </span><span class="n">can</span><span class="w"> </span><span class="n">easily</span><span class="w"> </span><span class="n">prove</span><span class="w"> </span><span class="n">what</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">describe</span><span class="o">:</span>
<span class="w"> </span><span class="n">$</span><span class="w"> </span><span class="n">cat</span><span class="w"> </span><span class="n">test</span><span class="p">.</span><span class="n">adb</span>
<span class="w"> </span><span class="n">procedure</span><span class="w"> </span><span class="n">Test</span><span class="w"> </span><span class="p">(</span><span class="n">X</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">Integer</span><span class="p">)</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="n">Pre</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="n">X</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="mi">5</span><span class="p">,</span><span class="w"> </span><span class="n">SPARK_Mode</span><span class="w"> </span><span class="n">is</span>
<span class="w"> </span><span class="n">begin</span>
<span class="w"> </span><span class="n">pragma</span><span class="w"> </span><span class="n">Assert</span><span class="w"> </span><span class="p">(</span><span class="n">Float</span><span class="w"> </span><span class="p">(</span><span class="n">X</span><span class="p">)</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="mf">5.0</span><span class="p">);</span>
<span class="w"> </span><span class="n">end</span><span class="p">;</span>
<span class="w"> </span><span class="n">$</span><span class="w"> </span><span class="n">gnatprove</span><span class="w"> </span><span class="o">-</span><span class="n">P</span><span class="w"> </span><span class="n">test</span><span class="p">.</span><span class="n">gpr</span><span class="w"> </span><span class="o">-</span><span class="n">f</span><span class="w"> </span><span class="o">--</span><span class="n">report</span><span class="o">=</span><span class="n">statistics</span>
<span class="w"> </span><span class="n">Phase</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="mi">2</span><span class="o">:</span><span class="w"> </span><span class="n">generation</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">Global</span><span class="w"> </span><span class="n">contracts</span><span class="w"> </span><span class="p">...</span>
<span class="w"> </span><span class="n">Phase</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="mi">2</span><span class="o">:</span><span class="w"> </span><span class="n">flow</span><span class="w"> </span><span class="n">analysis</span><span class="w"> </span><span class="n">and</span><span class="w"> </span><span class="n">proof</span><span class="w"> </span><span class="p">...</span>
<span class="w"> </span><span class="n">test</span><span class="p">.</span><span class="n">adb</span><span class="o">:</span><span class="mi">1</span><span class="o">:</span><span class="mi">11</span><span class="o">:</span><span class="w"> </span><span class="n">warning</span><span class="o">:</span><span class="w"> </span><span class="n">subprogram</span><span class="w"> </span><span class="s">"Test"</span><span class="w"> </span><span class="n">has</span><span class="w"> </span><span class="n">no</span><span class="w"> </span><span class="n">effect</span>
<span class="w"> </span><span class="n">test</span><span class="p">.</span><span class="n">adb</span><span class="o">:</span><span class="mi">3</span><span class="o">:</span><span class="mi">19</span><span class="o">:</span><span class="w"> </span><span class="n">info</span><span class="o">:</span><span class="w"> </span><span class="n">assertion</span><span class="w"> </span><span class="n">proved</span><span class="w"> </span><span class="p">(</span><span class="n">CVC4</span><span class="o">:</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">VC</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">max</span><span class="w"> </span><span class="mf">0.0</span><span class="w"> </span><span class="n">seconds</span><span class="w"> </span><span class="n">and</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">step</span><span class="p">)</span>
<span class="w"> </span><span class="n">test</span><span class="p">.</span><span class="n">adb</span><span class="o">:</span><span class="mi">3</span><span class="o">:</span><span class="mi">26</span><span class="o">:</span><span class="w"> </span><span class="n">info</span><span class="o">:</span><span class="w"> </span><span class="n">range</span><span class="w"> </span><span class="n">check</span><span class="w"> </span><span class="n">proved</span><span class="w"> </span><span class="p">(</span><span class="n">Interval</span><span class="p">)</span>
<span class="w"> </span><span class="n">Summary</span><span class="w"> </span><span class="n">logged</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="o">/</span><span class="n">tmp</span><span class="o">/</span><span class="n">flo</span><span class="o">/</span><span class="n">gnatprove</span><span class="o">/</span><span class="n">gnatprove</span><span class="p">.</span><span class="k">out</span>
<span class="n">Finally</span><span class="p">,</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">SPARK</span><span class="w"> </span><span class="n">Pro</span><span class="w"> </span><span class="k">release</span><span class="w"> </span><span class="n">can</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">CodePeer</span><span class="w"> </span><span class="n">analyser</span><span class="w"> </span><span class="n">and</span><span class="w"> </span><span class="n">as</span><span class="w"> </span><span class="n">described</span>
<span class="k">in</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">User</span><span class="err">'</span><span class="n">s</span><span class="w"> </span><span class="n">Guide</span><span class="o">:</span>
<span class="w"> </span><span class="s">"CodePeer analysis is particularly interesting when analyzing code using</span>
<span class="w"> </span><span class="n">floating</span><span class="o">-</span><span class="n">point</span><span class="w"> </span><span class="n">computations</span><span class="p">,</span><span class="w"> </span><span class="n">as</span><span class="w"> </span><span class="n">CodePeer</span><span class="w"> </span><span class="n">is</span><span class="w"> </span><span class="n">both</span><span class="w"> </span><span class="n">fast</span><span class="w"> </span><span class="n">and</span><span class="w"> </span><span class="n">precise</span><span class="w"> </span><span class="k">for</span>
<span class="w"> </span><span class="n">proving</span><span class="w"> </span><span class="n">bounds</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">floating</span><span class="o">-</span><span class="n">point</span><span class="w"> </span><span class="n">operations</span><span class="p">.</span><span class="s">"</span>
<span class="w"> </span><span class="nl">http</span><span class="p">:</span><span class="c1">//docs.adacore.com/spark2014-docs/html/ug/en/source/how_to_run_gnatprove.html#using-codepeer-static-analy</span>
<span class="o">*</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">Post</span><span class="w"> </span><span class="n">aspect</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">non</span><span class="o">-</span><span class="n">recursive</span><span class="w"> </span><span class="n">Isqrt</span><span class="w"> </span><span class="n">function</span><span class="w"> </span><span class="n">can</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">simplified</span><span class="w"> </span><span class="o">:</span><span class="p">)</span><span class="w"> </span><span class="n">i</span><span class="p">.</span><span class="n">e</span><span class="p">.</span>
<span class="w"> </span><span class="n">Post</span><span class="w"> </span><span class="o">=></span>
<span class="w"> </span><span class="p">(</span><span class="k">if</span><span class="w"> </span><span class="n">num</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">AAA</span><span class="w"> </span><span class="n">then</span><span class="w"> </span><span class="n">XXX</span><span class="p">)</span>
<span class="w"> </span><span class="n">and</span><span class="w"> </span><span class="n">then</span>
<span class="w"> </span><span class="p">(</span><span class="k">if</span><span class="w"> </span><span class="n">num</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="n">AAA</span><span class="w"> </span><span class="n">then</span><span class="w"> </span><span class="n">YYY</span><span class="p">);</span>
<span class="w"> </span><span class="n">is</span><span class="w"> </span><span class="n">equivalent</span><span class="w"> </span><span class="n">to</span>
<span class="w"> </span><span class="n">Post</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="p">(</span><span class="k">if</span><span class="w"> </span><span class="n">num</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">AAA</span><span class="w"> </span><span class="n">then</span><span class="w"> </span><span class="n">XXX</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="n">YYY</span><span class="p">);</span>
<span class="o">*</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">don</span><span class="err">'</span><span class="n">t</span><span class="w"> </span><span class="n">really</span><span class="w"> </span><span class="n">need</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">special</span><span class="o">-</span><span class="k">case</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="no">and</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="no">I</span><span class="w"> </span><span class="no">believe</span><span class="err">;</span><span class="w"> </span><span class="no">you</span><span class="w"> </span><span class="no">can</span><span class="w"> </span><span class="no">handle</span><span class="w"> </span><span class="no">them</span>
<span class="w"> </span><span class="no">in</span><span class="w"> </span><span class="no">the</span><span class="w"> </span><span class="no">FOR</span><span class="w"> </span><span class="no">loop</span><span class="p">,</span><span class="w"> </span><span class="no">i</span><span class="p">.</span><span class="no">e</span><span class="p">.:</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">..</span><span class="w"> </span><span class="mi">46340</span><span class="w"> </span><span class="n">loop</span><span class="w"> </span><span class="p">...</span>
<span class="o">*</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">can</span><span class="w"> </span><span class="n">nest</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="s">"inner"</span><span class="w"> </span><span class="n">function</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">recursive</span><span class="w"> </span><span class="n">implementation</span><span class="w"> </span><span class="n">inside</span>
<span class="w"> </span><span class="n">Isqrt2</span><span class="w"> </span><span class="n">and</span><span class="w"> </span><span class="n">then</span><span class="w"> </span><span class="n">it</span><span class="w"> </span><span class="n">won</span><span class="err">'</span><span class="n">t</span><span class="w"> </span><span class="n">need</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="s">"num"</span><span class="w"> </span><span class="n">parameter</span><span class="p">,</span><span class="w"> </span><span class="n">i</span><span class="p">.</span><span class="n">e</span><span class="p">.</span><span class="o">:</span>
<span class="w"> </span><span class="n">function</span><span class="w"> </span><span class="n">Isqrt2</span><span class="w"> </span><span class="p">(</span><span class="n">num</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">Natural</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">Natural</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="n">is</span>
<span class="w"> </span><span class="n">function</span><span class="w"> </span><span class="n">Isqrt2_inner</span><span class="w"> </span><span class="p">(</span><span class="n">lo</span><span class="p">,</span><span class="w"> </span><span class="n">hi</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">Natural</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">Natural</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="n">is</span>
<span class="w"> </span><span class="n">begin</span>
<span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="n">here</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">can</span><span class="w"> </span><span class="n">reference</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">parameter</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">enclosing</span><span class="w"> </span><span class="n">routine</span><span class="w"> </span><span class="p">...</span>
<span class="w"> </span><span class="n">end</span><span class="w"> </span><span class="n">Isqrt2_inner</span><span class="p">;</span>
<span class="w"> </span><span class="n">begin</span>
<span class="w"> </span><span class="p">...</span>
<span class="w"> </span><span class="n">end</span><span class="w"> </span><span class="n">Isqrt</span><span class="p">;</span>
<span class="w"> </span><span class="n">This</span><span class="w"> </span><span class="n">could</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">marginally</span><span class="w"> </span><span class="n">faster</span><span class="w"> </span><span class="p">(</span><span class="n">because</span><span class="w"> </span><span class="n">less</span><span class="w"> </span><span class="n">data</span><span class="w"> </span><span class="n">is</span><span class="w"> </span><span class="n">put</span><span class="w"> </span><span class="n">on</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">stack</span><span class="w"> </span><span class="n">when</span>
<span class="w"> </span><span class="n">calling</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="s">"inner"</span><span class="w"> </span><span class="n">routine</span><span class="p">),</span><span class="w"> </span><span class="n">but</span><span class="w"> </span><span class="n">I</span><span class="w"> </span><span class="n">didn</span><span class="err">'</span><span class="n">t</span><span class="w"> </span><span class="n">measure</span><span class="p">.</span>
<span class="o">*</span><span class="w"> </span><span class="s">"I tried to prove that Main behaves correctly, but unfortunaly the Text_IO</span>
<span class="w"> </span><span class="n">functions</span><span class="w"> </span><span class="k">do</span><span class="w"> </span><span class="n">not</span><span class="w"> </span><span class="n">provide</span><span class="w"> </span><span class="n">any</span><span class="w"> </span><span class="n">suitable</span><span class="w"> </span><span class="n">contracts</span><span class="s">"</span>
<span class="n">The</span><span class="w"> </span><span class="n">warnings</span><span class="w"> </span><span class="n">that</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">see</span><span class="w"> </span><span class="k">do</span><span class="w"> </span><span class="n">not</span><span class="w"> </span><span class="n">prevent</span><span class="w"> </span><span class="n">gnatprove</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="n">proving</span><span class="w"> </span><span class="n">your</span><span class="w"> </span><span class="n">code</span><span class="o">!</span>
<span class="n">They</span><span class="w"> </span><span class="n">only</span><span class="w"> </span><span class="n">mean</span><span class="w"> </span><span class="n">that</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">side</span><span class="o">-</span><span class="n">effect</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">writing</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">standard</span><span class="w"> </span><span class="n">output</span><span class="w"> </span><span class="n">is</span><span class="w"> </span><span class="n">not</span>
<span class="n">modelled</span><span class="w"> </span><span class="n">by</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">tool</span><span class="w"> </span><span class="p">(</span><span class="n">which</span><span class="w"> </span><span class="n">only</span><span class="w"> </span><span class="n">matters</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">are</span><span class="w"> </span><span class="n">paranoid</span><span class="w"> </span><span class="n">about</span><span class="w"> </span><span class="n">leaking</span><span class="w"> </span><span class="n">the</span>
<span class="n">information</span><span class="w"> </span><span class="k">out</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">your</span><span class="w"> </span><span class="n">program</span><span class="p">).</span>
<span class="o">*</span><span class="w"> </span><span class="s">"Unfortunately I don't have [the SPARK.Ada.Text_IO] package in my setup."</span>
<span class="n">You</span><span class="w"> </span><span class="n">should</span><span class="w"> </span><span class="n">have</span><span class="w"> </span><span class="n">it</span><span class="w"> </span><span class="n">as</span><span class="w"> </span><span class="n">share</span><span class="o">/</span><span class="n">examples</span><span class="o">/</span><span class="n">spark</span><span class="o">/</span><span class="n">spark_io</span><span class="o">/</span><span class="n">spark</span><span class="o">-</span><span class="n">text_io</span><span class="p">.</span><span class="n">ads</span><span class="p">.</span><span class="w"> </span><span class="n">It</span><span class="w"> </span><span class="n">was</span>
<span class="n">included</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">both</span><span class="w"> </span><span class="mi">2017</span><span class="w"> </span><span class="n">and</span><span class="w"> </span><span class="mi">2018</span><span class="w"> </span><span class="n">releases</span><span class="p">.</span>
<span class="n">And</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">your</span><span class="w"> </span><span class="n">latest</span><span class="w"> </span><span class="n">blog</span><span class="w"> </span><span class="n">post</span><span class="w"> </span><span class="n">on</span><span class="w"> </span><span class="n">Frama</span><span class="o">-</span><span class="n">C</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">say</span><span class="o">:</span>
<span class="o">*</span><span class="w"> </span><span class="s">"The assigns clause is something we didn't see in Ada SPARK."</span>
<span class="n">It</span><span class="w"> </span><span class="n">looks</span><span class="w"> </span><span class="n">like</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">missed</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">whole</span><span class="w"> </span><span class="n">lot</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">SPARK</span><span class="err">'</span><span class="n">s</span><span class="w"> </span><span class="n">functionality</span><span class="o">!</span><span class="w"> </span><span class="n">The</span><span class="w"> </span><span class="s">"assign"</span>
<span class="k">in</span><span class="w"> </span><span class="n">Frama</span><span class="o">-</span><span class="n">C</span><span class="w"> </span><span class="n">is</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">simple</span><span class="w"> </span><span class="n">variant</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">Global</span><span class="w"> </span><span class="n">contract</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">SPARK</span><span class="p">.</span><span class="w"> </span><span class="n">See</span>
<span class="nl">http</span><span class="p">:</span><span class="c1">//docs.adacore.com/spark2014-docs/html/ug/en/source/subprogram_contracts.html#data-dependencies</span>
<span class="n">You</span><span class="w"> </span><span class="n">might</span><span class="w"> </span><span class="n">also</span><span class="w"> </span><span class="n">want</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">explore</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">Depends</span><span class="w"> </span><span class="n">contract</span><span class="p">,</span><span class="w"> </span><span class="n">which</span><span class="w"> </span><span class="n">carries</span><span class="w"> </span><span class="n">even</span><span class="w"> </span><span class="n">more</span>
<span class="n">information</span><span class="w"> </span><span class="n">than</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">Global</span><span class="p">;</span><span class="w"> </span><span class="n">Frama</span><span class="o">-</span><span class="n">C</span><span class="w"> </span><span class="n">doesn</span><span class="err">'</span><span class="n">t</span><span class="w"> </span><span class="n">have</span><span class="w"> </span><span class="n">anything</span><span class="w"> </span><span class="n">like</span><span class="w"> </span><span class="n">that</span><span class="p">.</span>
<span class="o">*</span><span class="w"> </span><span class="s">"[in SPARK] every program must terminate"</span>
<span class="n">This</span><span class="w"> </span><span class="n">is</span><span class="w"> </span><span class="n">not</span><span class="w"> </span><span class="n">quite</span><span class="w"> </span><span class="nb">true</span><span class="p">,</span><span class="w"> </span><span class="n">because</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">can</span><span class="w"> </span><span class="n">annotate</span><span class="w"> </span><span class="n">procedures</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">No_Return</span>
<span class="nl">aspect</span><span class="w"> </span><span class="p">:)</span><span class="w"> </span><span class="n">However</span><span class="p">,</span><span class="w"> </span><span class="n">termination</span><span class="w"> </span><span class="n">is</span><span class="w"> </span><span class="n">indeed</span><span class="w"> </span><span class="n">an</span><span class="w"> </span><span class="n">important</span><span class="w"> </span><span class="n">issue</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">SPARK</span><span class="w"> </span><span class="n">and</span><span class="w"> </span><span class="n">we</span>
<span class="n">describe</span><span class="w"> </span><span class="n">it</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">detail</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">User</span><span class="err">'</span><span class="n">s</span><span class="w"> </span><span class="n">Guide</span><span class="o">:</span>
<span class="nl">http</span><span class="p">:</span><span class="c1">//docs.adacore.com/spark2014-docs/html/ug/en/source/how_to_write_subprogram_contracts.html#subprogram-termination</span>
<span class="o">*</span><span class="w"> </span><span class="p">[</span><span class="n">subprograms</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">SPARK</span><span class="p">]</span><span class="w"> </span><span class="n">can</span><span class="err">'</span><span class="n">t</span><span class="w"> </span><span class="n">perform</span><span class="w"> </span><span class="n">dynamic</span><span class="w"> </span><span class="n">memory</span><span class="w"> </span><span class="n">allocation</span><span class="s">"</span>
<span class="n">Hopefully</span><span class="w"> </span><span class="n">not</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="kt">long</span><span class="o">!</span><span class="w"> </span><span class="n">See</span><span class="w"> </span><span class="n">https</span><span class="o">:</span><span class="c1">//www.reddit.com/r/ada/comments/8jsyl2/borrowing_safe_pointers_from_rust_in_spark/</span>
<span class="n">I</span><span class="w"> </span><span class="n">am</span><span class="w"> </span><span class="n">looking</span><span class="w"> </span><span class="n">forward</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">read</span><span class="w"> </span><span class="n">about</span><span class="w"> </span><span class="n">your</span><span class="w"> </span><span class="n">experience</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="n">other</span><span class="w"> </span><span class="n">tools</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">the</span>
<span class="n">formal</span><span class="w"> </span><span class="n">verification</span><span class="o">!</span><span class="w"> </span><span class="n">If</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">find</span><span class="w"> </span><span class="n">any</span><span class="w"> </span><span class="n">issues</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">SPARK</span><span class="w"> </span><span class="n">toolchain</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">the</span>
<span class="n">future</span><span class="p">,</span><span class="w"> </span><span class="n">please</span><span class="w"> </span><span class="k">do</span><span class="w"> </span><span class="n">not</span><span class="w"> </span><span class="n">hesitate</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">ask</span><span class="w"> </span><span class="n">at</span><span class="w"> </span><span class="n">spark2014</span><span class="o">-</span><span class="n">discuss</span><span class="p">@</span><span class="n">lists</span><span class="p">.</span><span class="n">adacore</span><span class="p">.</span><span class="n">com</span><span class="p">.</span>
<span class="o">--</span>
<span class="n">Piotr</span>
</code></pre></div>Changed landing page, create_article.sh2017-12-24T13:07:10+01:002017-12-24T13:07:10+01:00tomastag:www.härdin.se,2017-12-24:/blog/2017/12/24/changed-landing-page-create-article-sh/<p>I have changed the site so that what used to be the "about" page is now the landing page.
The only tricky thing with this is that some URL metadata had to be set so that
clicking on "Home" brings the user to the root of the site. Like so …</p><p>I have changed the site so that what used to be the "about" page is now the landing page.
The only tricky thing with this is that some URL metadata had to be set so that
clicking on "Home" brings the user to the root of the site. Like so:</p>
<div class="highlight"><pre><span></span><code>Title: Home
URL:
save_as: index.html
Welcome!
</code></pre></div>
<p>I also added a line to pelicanconf.py to prevent it from generating index2.html, index3.html and so on:</p>
<div class="highlight"><pre><span></span><code><span class="n">INDEX_SAVE_AS</span> <span class="o">=</span> <span class="kc">None</span>
</code></pre></div>
<p>In order to make writing future articles easier I also wrote myself a short
script which asks for title and optional category (default: Blog) and generates
date, slug, author etc.:</p>
<div class="highlight"><pre><span></span><code><span class="nb">set</span><span class="w"> </span>-e
<span class="nb">read</span><span class="w"> </span>-p<span class="w"> </span><span class="s2">"Title? "</span><span class="w"> </span>TITLE
<span class="o">[[</span><span class="w"> </span>-z<span class="w"> </span><span class="nv">$TITLE</span><span class="w"> </span><span class="o">]]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="nb">echo</span><span class="w"> </span>aborted<span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="nb">exit</span><span class="w"> </span><span class="m">1</span>
<span class="nv">SLUG</span><span class="o">=</span><span class="k">$(</span>tr<span class="w"> </span>A-Z<span class="w"> </span>a-z<span class="w"> </span><span class="o"><<<</span><span class="w"> </span><span class="s2">"</span><span class="nv">$TITLE</span><span class="s2">"</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>sed<span class="w"> </span>-e<span class="w"> </span><span class="s1">'s/[^a-z0-9-]/ /g;s/ [ ]*/-/g;s/-[-]*$//'</span><span class="k">)</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"Title: </span><span class="nv">$TITLE</span><span class="s2">"</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"Slug: </span><span class="nv">$SLUG</span><span class="s2">"</span>
<span class="nb">read</span><span class="w"> </span>-p<span class="w"> </span><span class="s2">"Category? [Blog] "</span><span class="w"> </span>CATEGORY
<span class="k">if</span><span class="w"> </span><span class="o">[[</span><span class="w"> </span>-z<span class="w"> </span><span class="s2">"</span><span class="nv">$CATEGORY</span><span class="s2">"</span><span class="w"> </span><span class="o">]]</span><span class="p">;</span><span class="w"> </span><span class="k">then</span><span class="w"> </span><span class="nv">CATEGORY</span><span class="o">=</span>Blog<span class="w"> </span><span class="p">;</span><span class="w"> </span><span class="k">fi</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">"Title: </span><span class="nv">$TITLE</span>
<span class="s2">Date: </span><span class="k">$(</span>date<span class="w"> </span>--rfc-3339<span class="o">=</span>seconds<span class="k">)</span>
<span class="s2">Author: tomas</span>
<span class="s2">Category: </span><span class="nv">$CATEGORY</span>
<span class="s2">Tags:</span>
<span class="s2">Slug: </span><span class="nv">$SLUG</span>
<span class="s2">Status: published</span>
<span class="s2">Put ze text here.</span>
<span class="s2">"</span><span class="w"> </span>><span class="w"> </span>content/<span class="nv">$SLUG</span>.md
./develop_server.sh<span class="w"> </span>start<span class="w"> </span><span class="m">8080</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="nb">echo</span><span class="w"> </span>already<span class="w"> </span>up
firefox<span class="w"> </span>http://localhost:8080/category/blog.html
nano<span class="w"> </span>content/<span class="nv">$SLUG</span>.md
./develop_server.sh<span class="w"> </span>stop
</code></pre></div>
<p>I also made develop_server.sh not spam the terminal:</p>
<div class="highlight"><pre><span></span><code><span class="gd">- $PELICAN --debug --autoreload -r $INPUTDIR -o $OUTPUTDIR -s $CONFFILE $PELICANOPTS &</span>
<span class="gi">+ $PELICAN --autoreload -r $INPUTDIR -o $OUTPUTDIR -s $CONFFILE $PELICANOPTS > /dev/null 2> /dev/null &</span>
<span class="w"> </span> pelican_pid=$!
<span class="w"> </span> echo $pelican_pid > $PELICAN_PID
<span class="w"> </span> mkdir -p $OUTPUTDIR && cd $OUTPUTDIR
<span class="gd">- $PY -m pelican.server $port &</span>
<span class="gi">+ $PY -m pelican.server $port > /dev/null 2> /dev/null &</span>
</code></pre></div>40years2017-12-09T00:00:00+01:002017-12-09T00:00:00+01:00tomastag:www.härdin.se,2017-12-09:/demoscene/2017/12/09/40years/<p>A celebration of the Atari VCS (aka Stella) turning 40 years.
My contributions were among other things the new graphics mode used for the picture of Nolan Bushnell, the joystick candle and 3D animation.
Also build system and timing stuff.
Development started on 2017-09-01, so the whole process took a …</p><p>A celebration of the Atari VCS (aka Stella) turning 40 years.
My contributions were among other things the new graphics mode used for the picture of Nolan Bushnell, the joystick candle and 3D animation.
Also build system and timing stuff.
Development started on 2017-09-01, so the whole process took a bit over three months.
Lost 1st place to <a href="https://www.pouet.net/prod.php?which=72716">Egypt, 2600BC</a>, a well-deserved win for Genesis Project :)</p>Imported comments, smarter Makefile2017-09-17T19:47:26+02:002017-09-17T19:47:26+02:00tomastag:www.härdin.se,2017-09-17:/blog/2017/09/17/imported-comments-smarter-makefile/<p>Finally got around to importing the comments from the old WordPress site into pelican.
I had in mind to write some kind of automatic script to do this,
but there were only 11 comments in total which didn't justify spending the time writing a script for it.
So I did …</p><p>Finally got around to importing the comments from the old WordPress site into pelican.
I had in mind to write some kind of automatic script to do this,
but there were only 11 comments in total which didn't justify spending the time writing a script for it.
So I did them all by hand. I only had comments on these three articles:</p>
<ul>
<li><a href="http://www.härdin.se/blog/2015/06/10/music-tech-fest/">Music Tech Fest</a></li>
<li><a href="http://www.härdin.se/blog/2015/08/04/quick-and-dirty-nfm-transmitter-in-gnu-radio/">Quick and dirty NFM transmitter in GNU Radio</a></li>
<li><a href="http://www.härdin.se/blog/2016/02/05/setting-up-gnuradio-for-raspberry-pi-2/">Setting up GNURadio for Raspberry Pi 2</a></li>
</ul>
<p>In the future I'll be handling any comments coming in by e-mail manually,
posting the discussion on here if it proves interesting.</p>
<p>I also made the Makefile for the pelican stuff a bit smarter.
Now it only runs pelican if the input files actually changed.
That rule is constructed by listing all files in $(INPUTDIR) recursively,
then escaping spaces before giving the file list to make.
Like this:</p>
<div class="highlight"><pre><span></span><code><span class="c1"># Only generate if some file in INPUTDIR changed. Deal with spaces as well.</span>
<span class="o">$</span><span class="p">(</span><span class="n">OUTPUTDIR</span><span class="p">)</span><span class="o">/</span><span class="n">index</span><span class="o">.</span><span class="n">html</span><span class="p">:</span><span class="w"> </span><span class="o">$</span><span class="p">(</span><span class="n">shell</span><span class="w"> </span><span class="n">find</span><span class="w"> </span><span class="o">$</span><span class="p">(</span><span class="n">INPUTDIR</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="n">type</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">sed</span><span class="w"> </span><span class="o">-</span><span class="n">e</span><span class="w"> </span><span class="s1">'s/ /</span><span class="se">\\</span><span class="s1"> /g'</span><span class="p">)</span>
<span class="w"> </span><span class="o">$</span><span class="p">(</span><span class="n">PELICAN</span><span class="p">)</span><span class="w"> </span><span class="o">$</span><span class="p">(</span><span class="n">INPUTDIR</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="n">o</span><span class="w"> </span><span class="o">$</span><span class="p">(</span><span class="n">OUTPUTDIR</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="n">s</span><span class="w"> </span><span class="o">$</span><span class="p">(</span><span class="n">PUBLISHCONF</span><span class="p">)</span><span class="w"> </span><span class="o">$</span><span class="p">(</span><span class="n">PELICANOPTS</span><span class="p">)</span>
<span class="n">publish</span><span class="p">:</span><span class="w"> </span><span class="o">$</span><span class="p">(</span><span class="n">OUTPUTDIR</span><span class="p">)</span><span class="o">/</span><span class="n">index</span><span class="o">.</span><span class="n">html</span>
<span class="n">rsync_upload</span><span class="p">:</span><span class="w"> </span><span class="n">publish</span>
<span class="w"> </span><span class="n">rsync</span><span class="w"> </span><span class="o">-</span><span class="n">e</span><span class="w"> </span><span class="s2">"ssh -p $(SSH_PORT)"</span><span class="w"> </span><span class="o">-</span><span class="n">P</span><span class="w"> </span><span class="o">-</span><span class="n">rvzc</span><span class="w"> </span><span class="o">--</span><span class="n">delete</span><span class="w"> </span>\
<span class="w"> </span><span class="o">$</span><span class="p">(</span><span class="n">OUTPUTDIR</span><span class="p">)</span><span class="o">/</span><span class="w"> </span><span class="o">$</span><span class="p">(</span><span class="n">SSH_USER</span><span class="p">)</span><span class="err">@</span><span class="o">$</span><span class="p">(</span><span class="n">SSH_HOST</span><span class="p">):</span><span class="o">$</span><span class="p">(</span><span class="n">SSH_TARGET_DIR</span><span class="p">)</span><span class="w"> </span><span class="o">--</span><span class="n">cvs</span><span class="o">-</span><span class="n">exclude</span>
</code></pre></div>
<p>Now there only seems to be one issue left to deal with: HTTPS.
But since this site is read-only it's not very high on my list of priorities.
But it would be good for learning how <a href="https://letsencrypt.org/">Let's Encrypt</a> works.</p>Bye-bye, Google!2017-04-18T08:40:00+02:002017-04-18T08:40:00+02:00tomastag:www.härdin.se,2017-04-18:/blog/2017/04/18/bye-bye-google/<p>Just a little post celebrating removing the parts of this template which pulled stuff in from third-party domains,
namely fonts via Google and some broken link to html5.js hosted via Google Code.
I also pre-emptively removed some Google Analytics stuff in the template which doesn't seem to get pulled …</p><p>Just a little post celebrating removing the parts of this template which pulled stuff in from third-party domains,
namely fonts via Google and some broken link to html5.js hosted via Google Code.
I also pre-emptively removed some Google Analytics stuff in the template which doesn't seem to get pulled in but felt good removing either way.</p>
<p>This site is now roughly 200 KiB, of which 35 KiB are pictures that are loaded but not displayed (?) and 51 KiB a font that's not really needed.
The actual "meat" of the site is 49 KiB, which compresses down to ~13 KiB.</p>
<p>I've also noticed pelican-import did not import the comments from the old site.
I'm going to have to insert these manually.</p>More site fixes2017-04-16T16:37:00+02:002017-04-16T16:37:00+02:00tomastag:www.härdin.se,2017-04-16:/blog/2017/04/16/more-site-fixes/<p>Spent part of today fixing more things with this site.
I figured out that it's possible to have static "pages" just like WordPress,
so I've added one of those ("About").</p>
<p>I also fixed the default CSS ("nomyidea") to work with narrow browser windows.
Took about an hour to figure out …</p><p>Spent part of today fixing more things with this site.
I figured out that it's possible to have static "pages" just like WordPress,
so I've added one of those ("About").</p>
<p>I also fixed the default CSS ("nomyidea") to work with narrow browser windows.
Took about an hour to figure out how, which serves as a bit of a reminder why I don't work with webdev :)
Had to change widths to max-widths and fiddle with line-heights, margins and paddings.</p>Hello, Pelican!2017-04-15T13:28:00+02:002017-04-15T13:28:00+02:00tomastag:www.härdin.se,2017-04-15:/blog/2017/04/15/hello-pelican/<p>This is a post celebrating successfully switching this site/blog over to the static site generator <a href="https://getpelican.com">Pelican</a>.
Why is this a big deal? For a couple of reasons:</p>
<p>The first reason is that WordPress is a fairly "heavy" framework.
There's a lot of opportunity for security issues.
For a single-person …</p><p>This is a post celebrating successfully switching this site/blog over to the static site generator <a href="https://getpelican.com">Pelican</a>.
Why is this a big deal? For a couple of reasons:</p>
<p>The first reason is that WordPress is a fairly "heavy" framework.
There's a lot of opportunity for security issues.
For a single-person blog it's also rather too complex.
Having to log in every time and dealing with spam comments was a hassle.</p>
<p>The second reason is so I can uninstall PHP from the server,
a move in line with my goal of living a PHP free life :)</p>
<p>The final reason is that this allows me to write blog posts from my terminal.
This might mean I take the time to write stuff more often, since I don't have to deal with the slow/brittle JS based editor in WordPress.</p>
<p>The process of moving over to Pelican involved a number of steps.
First I had to export all posts from WordPress to an XML file.
Next I used pelican-import to convert the WordPress XML to a set of Markdown files.
I wrote a shell script to fix up the output of pelican-import in various ways,
mostly related to image captions.
I also had to make sure all the old WordPress uploads still worked, such as pictures and .grc files.
There is a slight issue currently since some of the uploads are videos, and each time I rebuild the site they are copied from
the content directory to the output directory.
There is a pull request on the Pelican GitHub page (<a href="https://github.com/getpelican/pelican/pull/1982">link</a>)
slated for version 3.8 which changes this copying to using hardlinks.
This makes the generation process much faster since it doesn't have to copy gigabytes of data every time.</p>
<p>One side-effect to switching to a static site is the loss of comment functionality.
I plan on handling comments via e-mail, and inserting any interesting ones manually in the relevant posts.
Optionally comments may be submitted over OStatus/Mastodon/GNU Social.</p>
<p>Things to do:</p>
<ul>
<li>CSS</li>
<li>Video transcoding + HTML generator script</li>
<li>Fix some of the videos that did not import properly</li>
<li>Thumbnail generation (unless Pelican already does that)</li>
<li>An "about" page</li>
<li>HTTPS via <a href="https://letsencrypt.org/">Let's Encrypt</a></li>
</ul>DRM is digital celluloid2016-11-25T23:05:00+01:002016-11-25T23:05:00+01:00tomastag:www.härdin.se,2016-11-25:/blog/2016/11/25/drm-is-digital-celluloid/<p>Just like the vast amount of film produced during the early years of
cinema, we have a similar issue now with DRM locking down culture so
that it will become inaccessible to future generations.</p>Taking a look at the blog again2016-09-03T02:10:00+02:002016-09-03T02:10:00+02:00tomastag:www.härdin.se,2016-09-03:/blog/2016/09/03/taking-a-look-at-the-blog-again/<p>Haven't posted anything here in a while, but I have some things to say
lately. Stay posted!</p>23cm QSO attempt2016-05-18T13:10:00+02:002016-05-18T13:10:00+02:00tomastag:www.härdin.se,2016-05-18:/blog/2016/05/18/23cm-qso-attempt/<p>Time for another radio post. Yesterday me and SA2KNG made an attempt at
holding a conversation (QSO) on the 23cm band. The plan was to use
HackRF to do narrowband FM modulation/demodulation on my end, with KNG
using proven equipment on his end. We only got as far as …</p><p>Time for another radio post. Yesterday me and SA2KNG made an attempt at
holding a conversation (QSO) on the 23cm band. The plan was to use
HackRF to do narrowband FM modulation/demodulation on my end, with KNG
using proven equipment on his end. We only got as far as him possibly
detecting a carrier from my location, which might have been the HackRF's
local oscillator. Future attempts may yield more success..</p>
<p><a href="../../../../../blog/wp-content/uploads/2016/05/tmp_25179-DSC_00191144774693.jpg"><img alt="23cm
setup, with Yagi-Uda antenna, HackRF and
laptop" src="../../../../../blog/wp-content/uploads/2016/05/tmp_25179-DSC_00191144774693-300x168.jpg"></a></p>
<p>23cm setup, with Yagi-Uda antenna, HackRF and laptop</p>Contributing a Golay encoder/decoder to codec22016-04-25T12:07:00+02:002016-04-25T12:07:00+02:00tomastag:www.härdin.se,2016-04-25:/blog/2016/04/25/contributing-a-golay-encoderdecoder-to-codec2/<p>I've been following the development of <a href="http://freedv.org">FreeDV</a>, a
libre very-low bitrate digital voice system for amateur radio. Central
to this is <a href="http://www.rowetel.com/blog/?page_id=452">codec2</a>, the codec
used in the system. A few days ago a thread popped on the
mailing list that the existing implementation of <a href="https://en.wikipedia.org/wiki/Binary_Golay_code">binary Golay
codes</a> was not (L …</p><p>I've been following the development of <a href="http://freedv.org">FreeDV</a>, a
libre very-low bitrate digital voice system for amateur radio. Central
to this is <a href="http://www.rowetel.com/blog/?page_id=452">codec2</a>, the codec
used in the system. A few days ago a thread popped on the
mailing list that the existing implementation of <a href="https://en.wikipedia.org/wiki/Binary_Golay_code">binary Golay
codes</a> was not (L)GPL
compatible and that a replacement was needed. Since I've held a bit of
an interest in forward error correction (FEC) lately I decided to take a
stab at reimplementation.</p>
<p>The implementation ended up not taking terribly long. The main issue was
that the old decoder would shift the return value of golay23_decode()
left 11 bits compared to golay23_encode() whereas my initial attempt
would do the most obvious thing, having
golay23_decode(golay23_encode(x)) == x. But once I figured this out
the rest was trivial.</p>
<p>The result of my efforts can now be seen in
<a href="https://svn.code.sf.net/p/freetel/code/codec2-dev/src/golay23.c">golay32.c</a>
on the codec2-dev SVN. This whole thing is also giving me inspiration to
continue further down the FEC path, which is especially relevant for the
<a href="http://www.umu.se/ViewPage.action?siteNodeId=4510&languageId=1&contentId=264613">ULV
project</a>
(putting a scientific instrument on the moon). I might do a post with
more information about that <a href="http://scube.se/blog/">on the other blog</a>..</p>Revision 20162016-04-04T21:40:00+02:002016-04-04T21:40:00+02:00tomastag:www.härdin.se,2016-04-04:/blog/2016/04/04/revision-2016/<p>Went to the <a href="https://2016.revision-party.net/">Revision</a> demoparty in
Saarbrücken this easter, which has become a bit of a tradition. The trip
went via a flight to Amsterdam, from which me and four others rented a
car and drove the rest of the way. The trip itself went quite well.
Didn't end up …</p><p>Went to the <a href="https://2016.revision-party.net/">Revision</a> demoparty in
Saarbrücken this easter, which has become a bit of a tradition. The trip
went via a flight to Amsterdam, from which me and four others rented a
car and drove the rest of the way. The trip itself went quite well.
Didn't end up producing any entries, which is unusual. But I was not
alone - jvb didn't have anything either, and we both just sort of poked
a little at various projects and hung out with people talking about all
kinds of things. Knoeki on the other hand was considerably more
productive, having two productions entered in the compos and winning
third place in the 2D demo competiion (congrats!)</p>
<p>On to the pictures:</p>
<p><a href="../../../../../blog/wp-content/uploads/2016/03/P3261611.jpg"><img alt="Tracked music
compo" src="../../../../../blog/wp-content/uploads/2016/03/P3261611-300x225.jpg"></a></p>
<p>Tracked music compo</p>
<p><a href="../../../../../blog/wp-content/uploads/2016/03/P3261612.jpg"><img alt="Knoeki's notoriously crusty/heavily modified
C64" src="../../../../../blog/wp-content/uploads/2016/03/P3261612-300x225.jpg"></a></p>
<p>Knoeki's notorious modified C64</p>
<p><a href="../../../../../blog/wp-content/uploads/2016/03/P3261620.jpg"><img alt="Nighttime bonfire with
people" src="../../../../../blog/wp-content/uploads/2016/03/P3261620-300x225.jpg"></a></p>
<p>Nighttime bonfire with people</p>
<p><a href="../../../../../blog/wp-content/uploads/2016/03/P3281629.jpg"><img alt="The
winner of the Wild compo, with their gigantic RGB LED display made from
a building
facade" src="../../../../../blog/wp-content/uploads/2016/03/P3281629-300x225.jpg"></a></p>
<p>The winner of the Wild compo, with their gigantic RGB LED display made
from a building facade</p>
<p><a href="../../../../../blog/wp-content/uploads/2016/03/P3261618.jpg"><img alt="Tried
to grab a shot of the full moon, went
so-so" src="../../../../../blog/wp-content/uploads/2016/03/P3261618-300x225.jpg"></a></p>
<p>Tried to grab a shot of the full moon, went so-so</p>
<p><a href="../../../../../blog/wp-content/uploads/2016/03/tmp_25468-DSC_00011864489147-e1459805833820.jpg"><img alt="Managed to snag a HACKERS poster, for Jupiter
666" src="../../../../../blog/wp-content/uploads/2016/03/tmp_25468-DSC_00011864489147-e1459805833820-300x294.jpg"></a></p>
<p>Managed to snag a <a href="http://www.pouet.net/groups.php?which=8051">HACKERS</a>
poster, for the ill-fated <a href="http://www.pouet.net/prod.php?which=65391">Jupiter
666</a> system</p>
<p>Didn't manage to snap many pictures of people this year, for some
reason. Maybe next year</p>Compiling KiCAD2016-03-18T18:47:00+01:002016-03-18T18:47:00+01:00tomastag:www.härdin.se,2016-03-18:/blog/2016/03/18/compiling-kicad/<p>While drawing some schematics for <a href="http://music.umeahackerspace.se/">Umeå Music Hack
Space</a> I noticed around half of my
footprints aren't working. Long story short, turns out I needed to
compile KiCAD because Debian chose to disable the Github plugin for
getting proper footprints. This post documents the process.</p>
<p>First install prerequisites per <a href="https://www.kicad.org/download/debian/">this …</a></p><p>While drawing some schematics for <a href="http://music.umeahackerspace.se/">Umeå Music Hack
Space</a> I noticed around half of my
footprints aren't working. Long story short, turns out I needed to
compile KiCAD because Debian chose to disable the Github plugin for
getting proper footprints. This post documents the process.</p>
<p>First install prerequisites per <a href="https://www.kicad.org/download/debian/">this
site</a>, plus a few more:</p>
<div class="highlight"><pre><span></span><code>apt-get install libwxbase3.0-dev libwxgtk3.0-dev libgl1-mesa-dev
</code></pre></div>
<p>libglew-dev libglm-dev libcurl4-openssl-dev libboost-dev <br>
libboost-thread-dev libboost-system-dev libboost-context-dev <br>
libboost-iostreams-dev libboost-locale-dev libboost-regex-dev <br>
libssl-dev wx-common swig libbz2-dev bzr</p>
<p>The Boost version at the time of writing was 1.58.</p>
<p>Download and extract the source code:</p>
<div class="highlight"><pre><span></span><code><span class="n">wget</span><span class="w"> </span><span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">launchpad</span><span class="o">.</span><span class="n">net</span><span class="o">/</span><span class="n">kicad</span><span class="o">/</span><span class="mf">4.0</span><span class="o">/</span><span class="mf">4.0</span><span class="o">.</span><span class="mi">2</span><span class="o">/+</span><span class="n">download</span><span class="o">/</span><span class="n">kicad</span><span class="o">-</span><span class="mf">4.0</span><span class="o">.</span><span class="mf">2.</span><span class="n">tar</span><span class="o">.</span><span class="n">xz</span>
<span class="n">dtrx</span><span class="w"> </span><span class="o">-</span><span class="n">n</span><span class="w"> </span><span class="n">kicad</span><span class="o">-</span><span class="mf">4.0</span><span class="o">.</span><span class="mf">2.</span><span class="n">tar</span><span class="o">.</span><span class="n">xz</span>
</code></pre></div>
<p>Configure using cmake:</p>
<div class="highlight"><pre><span></span><code>cd kicad-4.0.2
mkdir build
cd build
cmake .. -DKICAD_REPO_NAME=stable -DKICAD_BUILD_VERSION=4.0.2 -DKICAD_SCRIPTING=ON -DKICAD_SCRIPTING_MODULES=ON -DKICAD_SCRIPTING_WXPYTHON=ON -DCMAKE_CXX_FLAGS=-std=gnu++11 -DKICAD_SKIP_BOOST=ON
</code></pre></div>
<p>Finally, we're ready to compile:</p>
<div class="highlight"><pre><span></span><code>make -j3 -k; make; make
</code></pre></div>
<p>This will take half an hour or so, so go do some errands. The repeated
makes are due to KiCAD's build system having some kind of depency issue
or something. I have to "make" several times, so running it first with
-k should get as much as possible built, then the last two takes it the
rest of the way.</p>
<p>Finally, we're ready to install. As root just:</p>
<div class="highlight"><pre><span></span><code>make install
</code></pre></div>
<p>That's it!</p>youtube-play.sh2016-02-28T20:26:00+01:002016-02-28T20:26:00+01:00tomastag:www.härdin.se,2016-02-28:/blog/2016/02/28/youtube-play-sh/<p>In order to avoid having to run proprietary code from Google I cobbled
together a script a few days ago combining youtube-dl and vlc. The
result is far from perfect, but allows me to both download videos off of
YouTube for safekeeping and make use of features in vlc such …</p><p>In order to avoid having to run proprietary code from Google I cobbled
together a script a few days ago combining youtube-dl and vlc. The
result is far from perfect, but allows me to both download videos off of
YouTube for safekeeping and make use of features in vlc such as fixing
aspect ratios and incorrect cropping. I'm placing the following script
in the public domain, in the hope that it will be useful to someone:</p>
<div class="highlight"><pre><span></span><code><span class="n">TITLE</span><span class="o">=$</span><span class="p">(</span><span class="n">youtube</span><span class="o">-</span><span class="n">dl</span><span class="w"> </span><span class="o">-</span><span class="n">j</span><span class="w"> </span><span class="o">$</span><span class="mi">1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">sed</span><span class="w"> </span><span class="o">-</span><span class="n">e</span><span class="w"> </span><span class="s1">'s/.*"fulltitle": "//;s/".*//'</span><span class="p">)</span>
<span class="n">echo</span><span class="w"> </span><span class="o">$</span><span class="n">TITLE</span>
<span class="n">cd</span><span class="w"> </span><span class="o">/</span><span class="n">tmp</span>
<span class="n">youtube</span><span class="o">-</span><span class="n">dl</span><span class="w"> </span><span class="o">$</span><span class="mi">1</span><span class="w"> </span><span class="o">-</span><span class="n">o</span><span class="w"> </span><span class="s2">"$.mp4"</span><span class="w"> </span><span class="o">&</span>
<span class="c1"># A bit of an ugly hack here, but it works</span>
<span class="c1">#if [ -f "$.mp4" ]</span>
<span class="c1">#do</span>
<span class="c1"># # Already have the file</span>
<span class="c1"># vlc "$.mp4"</span>
<span class="c1"># exit 0</span>
<span class="c1">#done</span>
<span class="c1"># Wait for the download to start</span>
<span class="k">while</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="o">!</span><span class="w"> </span><span class="o">-</span><span class="n">f</span><span class="w"> </span><span class="s2">"$.mp4.part"</span><span class="w"> </span><span class="p">]</span>
<span class="n">do</span>
<span class="w"> </span><span class="n">echo</span><span class="w"> </span><span class="n">Waiting</span>
<span class="w"> </span><span class="n">sleep</span><span class="w"> </span><span class="mi">1</span>
<span class="n">done</span>
<span class="c1"># Wait a little more so we have some data..</span>
<span class="n">sleep</span><span class="w"> </span><span class="mi">1</span>
<span class="n">vlc</span><span class="w"> </span><span class="s2">"$.mp4.part"</span>
</code></pre></div>
<p>Some improvements could still be made. One issue is that sometimes the
download finished during the final sleep, so vlc get the wrong filename.
Meh!</p>
<p>edit: this feature is now built into both vlc and
<a href="https://mpv.io/">mpv</a>, and implemented much better. Yay!</p>Setting up GNURadio for Raspberry Pi 22016-02-05T15:22:00+01:002016-02-05T15:22:00+01:00tomastag:www.härdin.se,2016-02-05:/blog/2016/02/05/setting-up-gnuradio-for-raspberry-pi-2/<p>ACTUALLY just download <a href="http://garethhayes.net/gnu-radio-rtl_sdr-raspberry-pi/">this Raspbian
image</a> which
comes with gnuradio + hackrf + all the good stuff already (<a href="magnet:?xt=urn:btih:702c195d830d17a52ffc66f5b0db95338ad6202e&dn=gareth%5Fwheezygr.img.gz&tr=udp%3A%2F%2F11.rarbg.com%2Fannounce&tr=udp%3A%2F%2Ftracker.openbittorrent.com%3A80%2Fannounce&tr=udp%3A%2F%2Ftracker.istole.it%3A80%2Fannounce&tr=udp%3A%2F%2Ftracker.publicbt.com%3A80%2Fannounce&tr=udp%3A%2F%2Ftracker.ccc.de%3A80%2Fannounce&tr=udp%3A%2F%2Ffr33dom.h33t.com%3A3310%2Fannounce&tr=udp%3A%2F%2Ftracker.yify-torrents.com%3A80%2Fannounce&tr=udp%3A%2F%2Ftracker.prq.to%2Fannounce&tr=http%3A%2F%2Ftracker.yify-torrents.com%2Fannounce&tr=udp%3A%2F%2Ftracker.1337x.org%3A80%2Fannounce&tr=http%3A%2F%2Fwww.h33t.com%3A3310%2Fannounce&tr=http%3A%2F%2Fexodus.desync.com%2Fannounce&tr=http%3A%2F%2Ftracker.coppersurfer.tk%3A6969%2Fannounce&tr=http%3A%2F%2Ftracker.blazing.de%2Fannounce&tr=http%3A%2F%2F9.rarbg.com%3A2710%2Fannounce&tr=http%3A%2F%2Fbt.careland.com.cn%3A6969%2Fannounce&tr=udp%3A%2F%2Ftracker.ex.ua%3A80%2Fannounce&tr=udp%3A%2F%2Fcoppersurfer.tk%3A6969%2Fannounce&tr=udp%3A%2F%2Fipv4.tracker.harry.lu%3A80%2Fannounce&tr=udp%3A%2F%2F12.rarbg.me%3A80%2Fannounce&tr=udp%3A%2F%2F9.rarbg.com%3A2710%2Fannounce&tr=http%3A%2F%2Fexodus.desync.com%3A6969%2Fannounce">magnet
link</a>,
<a href="http://storage.transeam.net/files/gareth_wheezygr.img.gz">direct
link</a>).</p>
<p>Another possibility is to use the regular Raspbian image and add the
appropriate ppa with a prebuilt gnuradio in it. See <a href="http://www.rs-online.com/designspark/electronics/eng/blog/taking-the-raspberry-pi-2-for-a-test-drive-with-gnu-radio-2">this
link</a>
for more information about that. In short …</p><p>ACTUALLY just download <a href="http://garethhayes.net/gnu-radio-rtl_sdr-raspberry-pi/">this Raspbian
image</a> which
comes with gnuradio + hackrf + all the good stuff already (<a href="magnet:?xt=urn:btih:702c195d830d17a52ffc66f5b0db95338ad6202e&dn=gareth%5Fwheezygr.img.gz&tr=udp%3A%2F%2F11.rarbg.com%2Fannounce&tr=udp%3A%2F%2Ftracker.openbittorrent.com%3A80%2Fannounce&tr=udp%3A%2F%2Ftracker.istole.it%3A80%2Fannounce&tr=udp%3A%2F%2Ftracker.publicbt.com%3A80%2Fannounce&tr=udp%3A%2F%2Ftracker.ccc.de%3A80%2Fannounce&tr=udp%3A%2F%2Ffr33dom.h33t.com%3A3310%2Fannounce&tr=udp%3A%2F%2Ftracker.yify-torrents.com%3A80%2Fannounce&tr=udp%3A%2F%2Ftracker.prq.to%2Fannounce&tr=http%3A%2F%2Ftracker.yify-torrents.com%2Fannounce&tr=udp%3A%2F%2Ftracker.1337x.org%3A80%2Fannounce&tr=http%3A%2F%2Fwww.h33t.com%3A3310%2Fannounce&tr=http%3A%2F%2Fexodus.desync.com%2Fannounce&tr=http%3A%2F%2Ftracker.coppersurfer.tk%3A6969%2Fannounce&tr=http%3A%2F%2Ftracker.blazing.de%2Fannounce&tr=http%3A%2F%2F9.rarbg.com%3A2710%2Fannounce&tr=http%3A%2F%2Fbt.careland.com.cn%3A6969%2Fannounce&tr=udp%3A%2F%2Ftracker.ex.ua%3A80%2Fannounce&tr=udp%3A%2F%2Fcoppersurfer.tk%3A6969%2Fannounce&tr=udp%3A%2F%2Fipv4.tracker.harry.lu%3A80%2Fannounce&tr=udp%3A%2F%2F12.rarbg.me%3A80%2Fannounce&tr=udp%3A%2F%2F9.rarbg.com%3A2710%2Fannounce&tr=http%3A%2F%2Fexodus.desync.com%3A6969%2Fannounce">magnet
link</a>,
<a href="http://storage.transeam.net/files/gareth_wheezygr.img.gz">direct
link</a>).</p>
<p>Another possibility is to use the regular Raspbian image and add the
appropriate ppa with a prebuilt gnuradio in it. See <a href="http://www.rs-online.com/designspark/electronics/eng/blog/taking-the-raspberry-pi-2-for-a-test-drive-with-gnu-radio-2">this
link</a>
for more information about that. In short:</p>
<p>Edit /etc/apt/sources.list and add the following line:</p>
<div class="highlight"><pre><span></span><code><span class="k">deb</span><span class="w"> </span><span class="s">http://archive.raspbian.org/raspbian</span><span class="w"> </span><span class="kp">jessie</span><span class="w"> </span><span class="kp">main</span>
</code></pre></div>
<p>Then update apt and install gnuradio and gnuradio-dev:</p>
<div class="highlight"><pre><span></span><code>sudo apt-get update && sudo apt-get install gnuradio gnuradio-dev
</code></pre></div>
<p>Installing gqrx + osmocom + related stuff is also recommended:</p>
<div class="highlight"><pre><span></span><code>sudo apt-get install gr-osmosdr libosmosdr-dev gqrx-sdr
</code></pre></div>
<p>That should get you set up for developing with gnuradio, grc and related
python things :)</p>
<p>So far I've found 500 ksps is about the maximum samplerate the RPi2 can
handle when running gnuradio via Python. It might be possible to go
faster, since hackrf_transfer claims a transfer speed of 20 MiB/s is
possible (corresponding to 10 Msps).</p>
<p>I'm leaving the compilation guide I already started as-is, despite not
getting it to do what I wanted. Perhaps it'll be useful to someone:</p>
<hr>
<p>This post is an attempt at document my getting <a href="http://greatscottgadgets.com/hackrf/">hackRF
One</a> +
<a href="http://gnuradio.org/redmine/projects/gnuradio/wiki">GNURadio</a> running
on Raspberry Pi 2.</p>
<p>gnuradio requires CMake>=2.8.10 for NEON support, raspbian ships with
cmake 2.8.9. Grrmblr. So install that first:</p>
<div class="highlight"><pre><span></span><code>git clone https://cmake.org/cmake.git
cd cmake
git checkout v2.8.10
./configure && make -j3 && sudo make install
</code></pre></div>
<p>Three cores are used for make to speed things up (-j3). Four would cause
X to hang. Configuring and compiling cmake will take a while, so go grab
a coffee, do laundry or somesuch.</p>
<p>Next set up hackrf. I didn't record this step, but if I recall correctly
you need to download, compile and install gr-osmosdr. Something like
this:</p>
<div class="highlight"><pre><span></span><code>git clone git://git.osmocom.org/gr-osmosdr
cd gr-osmosdr
mkdir build
cd build
cmake ..
make -j3
sudo make install
</code></pre></div>
<p>You can check that you got it right by running hackrf_info, then
hackrf_transfer -c 127 -f 433960000 to check that the transmit
functionality works (remember to attach an antenna).</p>
<p>Finally it is time to install gnuradio itself. A small note on boost
here, since it always tends to be a problem for people stumbling upon
guides like this: I'm using version 1.49. At the time of writing the
latest version available via apt was 1.50. The latest official version
(outside Debian) was 1.60.0.</p>
<div class="highlight"><pre><span></span><code><span class="nv">sudo</span><span class="w"> </span><span class="nv">apt</span><span class="o">-</span><span class="nv">get</span><span class="w"> </span><span class="nv">install</span><span class="w"> </span><span class="nv">libboost</span><span class="o">-</span><span class="nv">dev</span><span class="w"> </span><span class="nv">libboost</span><span class="o">-</span><span class="nv">filesystem</span><span class="o">-</span><span class="nv">dev</span><span class="w"> </span>
<span class="w"> </span><span class="nv">libboost</span><span class="o">-</span><span class="nv">system</span><span class="o">-</span><span class="nv">dev</span><span class="w"> </span><span class="nv">libboost</span><span class="o">-</span><span class="nv">test</span><span class="o">-</span><span class="nv">dev</span><span class="w"> </span>
<span class="w"> </span><span class="nv">libboost</span><span class="o">-</span><span class="nv">program</span><span class="o">-</span><span class="nv">options</span><span class="o">-</span><span class="nv">dev</span><span class="w"> </span><span class="nv">python</span><span class="o">-</span><span class="nv">pip</span><span class="w"> </span><span class="nv">libcppunit</span><span class="o">-</span><span class="nv">dev</span><span class="w"> </span>
<span class="w"> </span><span class="nv">libfftw3</span><span class="o">-</span><span class="nv">dev</span><span class="w"> </span>#<span class="nv">TODO</span>:<span class="w"> </span><span class="nv">gr</span><span class="o">-</span><span class="nv">fft</span><span class="w"> </span><span class="nv">doesn</span><span class="err">'t build, figure out why</span>
<span class="err">sudo pip install cheetah</span>
<span class="err">git clone https://github.com/gnuradio/gnuradio.gitcd gnuradio</span>
<span class="err">git checkout 72dcbdb #optional, master as of writing</span>
<span class="err">git submodule init</span>
<span class="err">git submodule update</span>
<span class="err">mkdir build</span>
<span class="err">cd build</span>
<span class="err">cmake ..</span>
#<span class="w"> </span><span class="k">For</span><span class="w"> </span><span class="nv">some</span><span class="w"> </span><span class="nv">reason</span><span class="w"> </span><span class="nv">NEON</span><span class="w"> </span><span class="nv">doesn</span><span class="err">'t work, so disable it by in CMakeCache.txt changing the line</span>
<span class="err">#have_mfpu_neon:INTERNAL=1</span>
<span class="err"># to</span>
<span class="err">#have_mfpu_neon:INTERNAL=0</span>
<span class="err">nano CMakeCache.txt #do the thing</span>
<span class="err">make</span>
<span class="err">sudo make install</span>
</code></pre></div>
<p>This will build and install.. some parts of gnuradio. Not the Python
stuff though, which is what I need. Fffffff-</p>
<h1>Comments</h1>
<p><strong>Mike Mahoney</strong>, July 24, 2016 at 12:33 am</p>
<p>Running a new “Raspbian Jessie” image</p>
<p>Next set up hackrf.</p>
<div class="highlight"><pre><span></span><code>———————————-
Error during the “cmake . . ”
– Configuring Boost C++ Libraries…
– Could NOT find Boost
CMake Error at CMakeLists.txt:125 (message):
Boost required to build gr-osmosdr
– Configuring incomplete, errors occurred!
—————————————————————————
</code></pre></div>
<p>Recommendations?</p>
<p><strong>tomas</strong>, September 3, 2016 at 2:02 am</p>
<p>Install boost. Something like</p>
<div class="highlight"><pre><span></span><code>apt-get install libboost-dev
</code></pre></div>
<p>For a list of all boost dev packages do something like</p>
<div class="highlight"><pre><span></span><code>apt-cache search libboost|grep \\-dev
</code></pre></div>
<hr>
<p><strong>GAURAV PUROHIT</strong>, November 4, 2016 at 8:33 am</p>
<p>how to install gr-extra on pi for using pyserial and gr-pyserial</p>
<p><strong>tomas</strong>, November 25, 2016 at 11:03 pm</p>
<p>No idea. Maybe configure gnuradio with everything enabled? Can’t find a package named gr-extra or gnuradio-extra so don’t know what would be in it</p>
<hr>
<p><strong>GAURAV PUROHIT</strong>, November 4, 2016 at 8:34 am</p>
<p>who on pi, this is possible <a href="https://github.com/jmalsbury/gr-pyserial/wiki/Installation">https://github.com/jmalsbury/gr-pyserial/wiki/Installation</a></p>Star Wars: The Force Awakens2016-01-06T00:06:00+01:002016-01-06T00:06:00+01:00tomastag:www.härdin.se,2016-01-06:/blog/2016/01/06/star-wars-the-force-awakens/<p>Watched it. It was OK. Some sad men on the Web are up in arms about it
having a female lead. That's about all I can really say about it.</p>
<p>I also owe a penance to the EFF or whatever other organization I feel
deserves it, for having given 160 …</p><p>Watched it. It was OK. Some sad men on the Web are up in arms about it
having a female lead. That's about all I can really say about it.</p>
<p>I also owe a penance to the EFF or whatever other organization I feel
deserves it, for having given 160 SEK to the film industry.</p>Found an interesting blog2016-01-03T00:40:00+01:002016-01-03T00:40:00+01:00tomastag:www.härdin.se,2016-01-03:/blog/2016/01/03/found-an-interesting-blog/<p>Found the blog of retired research scientist Don P. Mitchell. Some
interesting stuff on there about space exploration, the Soviet space
program and sustainable technology:
<a href="https://donpmitchell.wordpress.com/">https://donpmitchell.wordpress.com/</a></p>On hackrf_transfer -c2015-11-04T11:12:00+01:002015-11-04T11:12:00+01:00tomastag:www.härdin.se,2015-11-04:/blog/2015/11/04/on-hackrf_transfer-c/<p>Just a quick post on hackrf_transfer's CW mode (-c). I've recently
taken a HackRF One to a signal analyzer in order to make sense of how
its DAC and gain values correspond to output power. In order to make use
of this in GNU Radio one needs to know what …</p><p>Just a quick post on hackrf_transfer's CW mode (-c). I've recently
taken a HackRF One to a signal analyzer in order to make sense of how
its DAC and gain values correspond to output power. In order to make use
of this in GNU Radio one needs to know what byte sequence going into the
DAC this corresponds to. Luckily this was easy to find out</p>
<p><a href="https://github.com/mossmann/hackrf/blob/master/host/hackrf-tools/src/hackrf_transfer.c%20">hackrf_transfer.c</a>
has a line that reads "transfer->buffer = amplitude;", which
implies the I/Q values sent are {amplitude,amplitude}. This means the
actual samples have values of amplitude*(1+i), which is 40% larger or
twice the amount of power than what you'd expect if say all the Qs were
zero. You can see something similar to this in GNURadio if you feed a
rectangular windowed FFT with "1" vs "1+1j" constant sources
(throttled). The former will have a 0 dBFS power while the latter will
have +3 dBFS. Sort of a "turning it up to eleven" kind of thing :)</p>
<p>A <a href="https://github.com/Tjoppen/rymdradio/commit/a35993e72134002560357d0e9cc054b848655edc">recent
commit</a>
to the git repository I have for this thing addresses this, such that
you can use the same parameters for my CW transmitter as
hackrf_transfer uses in its CW mode. Hopefully convenient!</p>Quick and dirty NFM transmitter in GNU Radio2015-08-04T10:04:00+02:002015-08-04T10:04:00+02:00tomastag:www.härdin.se,2015-08-04:/blog/2015/08/04/quick-and-dirty-nfm-transmitter-in-gnu-radio/<p>Since <a href="http://härdin.se/blog/2015/07/01/sa2tms-rapporterar/">getting my amateur radio
license</a> a while
back I haven't made much use of it, so yesterday I decided to try and do
something about that. Unfortunately the handheld Yaesu VX-6E I ordered
four weeks ago hasn't arrived yet, so I decided to go an alternate
route: figure out …</p><p>Since <a href="http://härdin.se/blog/2015/07/01/sa2tms-rapporterar/">getting my amateur radio
license</a> a while
back I haven't made much use of it, so yesterday I decided to try and do
something about that. Unfortunately the handheld Yaesu VX-6E I ordered
four weeks ago hasn't arrived yet, so I decided to go an alternate
route: figure out how to transmit narrowband FM using the <a href="http://greatscottgadgets.com/hackrf/">HackRF
One</a>. The goal of the evening
would be to get a conversation (QSO) going via the local VHF repeater on
145.650 MHz.</p>
<p>Some digging around on the Web showed that this is possible, but only as
a transmit-only thing. Two-way communication is still tricky. GRC might
not be a good enough tool for switching between TX and RX on a simplex
device like the HackRF.</p>
<p>I eventually managed to cobble together a reasonable <a href="http://gnuradio.org/redmine/projects/gnuradio/wiki">GNU
Radio</a> flow graph.
After some poking around, with
<a href="https://www.flickr.com/photos/knglaser/">SA2KNG</a> listening for my
attempts at reaching the outside world, we figured the transmit power
was too low, since even something very narrow like CW (Morse) was barely
making it through the \~5 km distance from my location to Umedalen.</p>
<p>More digging around revealed that the RF amplifier on the HackRF may
have some issues, and that there is an IF amplifier as well. Changing
the IF amplifier setting from the default of +20 dB to the maximum of
+47 dB made my signals go through quite well. It was time for the next
part of my plan: activating the local repeater.</p>
<p>Activating the repeater simply means transmitting a 1750 Hz tone, which
was relatively simple to extend the flow graph to do. The result was
people on IRC noting that there's a hell of a lot of beeping going on on
the repeater. But I wasn't hearing it. Why?</p>
<p>The answer turned out to be that the RTLSDR USB stick I was using for
listening (via <a href="http://gqrx.dk/">gqrx</a>) was not picking up the repeater,
but only my outgoing signal. A quickly constructed antenna (from a piece
of TV coax) fixed that problem, and I was now able to repeat the
experiment. I also added some courtesy features to the flow graph
(push-to-talk, tone generator on/off). The end result was a successful
(if noisy) QSO with SA2KNG. Success!</p>
<p>Picture time:</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/08/P7091571.jpg"><img alt="Transmitting antenna: 2 m/70 cm dipole" src="../../../../../blog/wp-content/uploads/2015/08/P7091571-300x225.jpg"></a></p>
<p>Transmitting antenna: 2 m/70 cm dipole</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/08/P8041573.jpg"><img alt="Receiving antenna: a 2 m dipole made from a piece of TV
coax" src="../../../../../blog/wp-content/uploads/2015/08/P8041573-300x225.jpg"></a></p>
<p>Receiving antenna: 2 m dipole made from a piece of TV coax</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/08/P8041572.jpg"><img alt="SDRs.
HackRF One and ezcap DVB-T FM DAB
(RTLSDR)" src="../../../../../blog/wp-content/uploads/2015/08/P8041572-300x225.jpg"></a></p>
<p>SDRs. HackRF One and ezcap DVB-T FM DAB (RTLSDR)</p>
<h2>GNU Radio notes</h2>
<p>Some random notes about GNU Radio while I'm at it:</p>
<p>There doesn't seem to be an easy way to implement a push-to-talk
feature. For now I have hacked one together using a GUI slider that
controls a "multiply const" box. The slider can only have the values "0"
or "1", so it can be moved by tabbing to it in the UI and pressing the
left/right arrow keys. I implemented a similar slider hack for enabling
the 1750 Hz tone generator. Another problem is having to use an RTLSDR
dongle for RX. I suspect this may be possible to fix by setting up a
flow graph with both an RX and TX part, then enabling/disabling the
relevant parts using some python code. The same python code could also
read the keyboard, and maybe switch channels.</p>
<p>Here's my code here in case someone else finds this interesting:
<a href="../../../../../blog/wp-content/uploads/2015/08/nbfm-tx.grc">nbfm-tx.grc</a>.
I've also attached a picture of the flow graph below:</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/08/flow-graph.png"><img alt="GRC
flow graph in picture
form" src="../../../../../blog/wp-content/uploads/2015/08/flow-graph-300x138.png"></a></p>
<p>GRC flow graph in picture form</p>
<h1>Comments</h1>
<p><strong>Juan Antonio</strong>, June 8, 2016 at 4:52 pm</p>
<p>Hi, i have been studyinmg your flowgraph and experimenting, but when i laucnh it, it begins to tx(red led in hackrf is lit) and when clicking on the slider to kick off the ptt, it stays on all the time. Is neccesary to get the slider connected to another block somehow?
Thanks in advance!!!</p>
<p><strong>tomas</strong>, September 3, 2016 at 2:09 am</p>
<p>This one is TX only (no RX in the flowgraph). I have other experiments which are able to switch between TX and RX, but it is very awkward. I brought this up in #gnuradio a while back, but there was no good way to fix it. What I’d like is a bidirectional block in GNU Radio Companion with a PTT input..</p>
<p>RX is done with RTL-SDR, if that wasn’t apparent.</p>On resonant cavity thrusters2015-07-28T11:33:00+02:002015-07-28T11:33:00+02:00tomastag:www.härdin.se,2015-07-28:/blog/2015/07/28/on-resonant-cavity-thrusters/<p>So the controversial
<a href="https://en.wikipedia.org/wiki/RF_resonant_cavity_thruster#EmDrive_2">EmDrive</a>
is making the rounds again, this time with a group of German
experimentalists claiming to have measured a net thrust of 20 µN for 700
W of input power (<a href="http://arc.aiaa.org/doi/abs/10.2514/6.2015-4083">link to paywalled
paper</a>). This post
isn't going to pass judgment on whether the effect is real …</p><p>So the controversial
<a href="https://en.wikipedia.org/wiki/RF_resonant_cavity_thruster#EmDrive_2">EmDrive</a>
is making the rounds again, this time with a group of German
experimentalists claiming to have measured a net thrust of 20 µN for 700
W of input power (<a href="http://arc.aiaa.org/doi/abs/10.2514/6.2015-4083">link to paywalled
paper</a>). This post
isn't going to pass judgment on whether the effect is real or not, but
rather whether it is actually of practical use given what has been
claimed so far. In order to do this I'm going to use a toy scenario I
like to think about every now and then: getting a PocketQube satellite
from low Earth orbit (LEO) to the Moon.</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/07/pocketqube.jpeg"><img alt="PocketQube" src="../../../../../blog/wp-content/uploads/2015/07/pocketqube-300x167.jpeg"></a>
PocketQube - the satellite form factor that fits in your
hand!</p>
<p>Since we're starting in LEO we first need to know: is this drive capable
of delivering enough thrust to keep our orbit from decaying? This means
compensating for drag, which according to Wikipedia is <a href="https://en.wikipedia.org/wiki/Delta-v_budget#Stationkeeping">somewhere
between 7.5 - 100 m/s per year depending on
altitude</a>.
The questions then are "how much power do we have?", "how high will our
thrust be?" and "how high is our mass?". For these I'm assuming a 5x5x5
cm PocketQube with maximum allowed mass (180 g).</p>
<p>If we have five of the sides of the satellite covered in solar panels,
folded out like flower petals and optimally aligned with the Sun, <a href="https://en.wikipedia.org/wiki/Monocrystalline_silicon#Efficiency">with
an efficiency of
20%</a>,
then our total power with an insolation of 1300 W/m² (solar constant)
becomes: 5*0.05²*1300*20% = 3.25 W. In LEO we're shaded by the Earth
roughly half of the time, so the average power becomes 3.25 / ≃ 1.6 W.
Assuming the thrust of the device is linear we then have an average
thrust of 20*1.6/700 ≃ 46 nN.</p>
<p>With a thrust of 46 nN and a mass of 180 g (0.18 kg) the average
acceleration becomes 256 nm/s². Over a year the accumulated delta-v is
256/10⁹*60*60*24*365 ≃ 8.1 m/s. In other words: if we get to start
at an altitude above 600 km we're probably not going to fall back down
again (but only just barely).</p>
<p>So, how long is this trip going to take us? Again I'm going to use
Wikipedia, and look up how much delta-v is needed to get from LEO to LLO
with this kind of low-thrust drive: <a href="https://en.wikipedia.org/wiki/Delta-v_budget#Earth.E2.80.93Moon_space.E2.80.94low_thrust">8.0
km/s</a>.
I'm also going to be kind and disregard the drag for this one: 8000 /
8.1 = 988 years (!). Now, it's been a while since we went to the Moon,
but something tells me if we're still around it's going to happen a lot
sooner than the year 3003 :)</p>
<p>Incidentally, this is why for electric propulsion thrust per unit of
power is much more important than specific impulse. All the efficiency
in the world isn't going to be of much use if you're dead by the time
your probe arrives at its destination..</p>SA2TMS rapporterar2015-07-01T20:23:00+02:002015-07-01T20:23:00+02:00tomastag:www.härdin.se,2015-07-01:/blog/2015/07/01/sa2tms-rapporterar/<p>Nu för något annorlunda: förra veckan skrev jag och tre andra i stan
prov för amatörradiocertifikat efter att ha haft en studiecirkel runt
detta i cirka en månad. FURA har skrivit lite kort om det, vilket kan
läsas via <a href="http://fura.se/index.php/nyheter/oevriga-nyheter/3113-fyra-4-nya-umea-signaler">denna
länk</a>.
Där finns även en oerhört fotogenisk bild på mig …</p><p>Nu för något annorlunda: förra veckan skrev jag och tre andra i stan
prov för amatörradiocertifikat efter att ha haft en studiecirkel runt
detta i cirka en månad. FURA har skrivit lite kort om det, vilket kan
läsas via <a href="http://fura.se/index.php/nyheter/oevriga-nyheter/3113-fyra-4-nya-umea-signaler">denna
länk</a>.
Där finns även en oerhört fotogenisk bild på mig!</p>
<p>Hursom damp själva licensen ner i brevlådan idag, stämplad och allt.
Callsign (även känt som signal) blev SA2TMS, där SA2 är beteckningen för
Sveriges nordligaste distrikt och TMS är vad jag valde som suffix i all
enkelhet.</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/07/P7011569-censurerat1.jpg"><img alt="SA2TMS - med rätt att
sända!" src="../../../../../blog/wp-content/uploads/2015/07/P7011569-censurerat1-300x225.jpg"></a></p>
<p>SA2TMS - med rätt att sända!</p>
<p>Nu frågar sig läsaren kanske vad detta ska vara bra till. Som allt annat
det här året kretsar detta såklart rund <a href="http://scube.se/">scube</a> och
våra månidéer. En av dessa är en låghastighetslänk mellan Jorden och
sonden, och detta är något vi gärna testar på marken gott om tid i
förväg. Planen för det är att placera en sändare och en mottagare på c:a
100 km avstånd (atmosfärens tjocklek) samt sända med en effekt som
motsvarar det vi kommer få emot om vi har säg 5W på månen - någonstans
runt 1 µW (mindre än en WiFi-accesspunkt men mer än en MP3-FM-sändare).
På detta blir det troligtvis något störkänsligt protokoll som
<a href="https://en.wikipedia.org/wiki/WSJT_%28Amateur_radio_software%29#JT65">JT65</a>
eller <a href="https://en.wikipedia.org/wiki/PSK31">PSK31</a>.</p>
<p>Det blev även återigen att lyssna efter internationella rymdstationen
ISS förra helgen, ett evenemang framförallt arrangerat av <a href="https://social.umeahackerspace.se/conversation/242733#notice-242733">Petter
Karkea</a>.
Vi fick inte kontakt med någon ombord, men vi (läs: <a href="http://radioinorr.se/">Peter
SA2BLV</a>) lyckades lämna ett meddelande i ISS
brevlåda. Tydligen ska det stå på ARISS hemsida, men det närmaste jag
hittar är att den snappat upp att <a href="http://www.findu.com/cgi-bin/find.cgi?SA2BLV">det är Peter som skickat
något</a>. Men en kul utflykt
likväl!</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/07/Omberget.jpg"><img alt="Deltagare vid Omberget 2015-06-28. CC-BY-SA Petter
Karkea" src="../../../../../blog/wp-content/uploads/2015/07/Omberget-200x300.jpg"></a></p>
<p>Deltagare vid Omberget 2015-06-28. CC-BY-SA Petter Karkea</p>
<p>En något mer underhållande användning blir nog att hålla kontakt med
ordentliga handradios under något gummibåtsrejs nedför Umeälven senare i
sommar.</p>
<p>Slut för denna gång!</p>Hubski2015-06-18T22:10:00+02:002015-06-18T22:10:00+02:00tomastag:www.härdin.se,2015-06-18:/blog/2015/06/18/hubski/<p>I suddenly realize I haven't plugged <a href="http://hubski.com/">hubski</a> on
this place yet. Hubski is one of many link aggregation/discussion sites
on the Web, but it has the distinguishing feature of people on there
being somewhat mature and educated when trying to discuss something.
I've been a member since about two …</p><p>I suddenly realize I haven't plugged <a href="http://hubski.com/">hubski</a> on
this place yet. Hubski is one of many link aggregation/discussion sites
on the Web, but it has the distinguishing feature of people on there
being somewhat mature and educated when trying to discuss something.
I've been a member since about two years (under a username I'm keeping
secret for now), and so far my stay has been rather pleasant.</p>
<p>Yes, it is a centralized service. But as centralized services go it's a
whole lot better than say reddit, a site which has only recently
realized that perhaps hosting a platform for neonazis and virulent fat
shamers is perhaps not the best thing to do..</p>
<p>I should also note here that some of the features that hubski implements
are things that <a href="https://gnu.io/social/">GNU Social/OStatus</a> has had
support for for years, but has yet to catch on in a major way. Neither
has hubski, of course. The future will show which one ends up being more
popular..</p>Music Tech Fest2015-06-10T21:49:00+02:002015-06-10T21:49:00+02:00tomastag:www.härdin.se,2015-06-10:/blog/2015/06/10/music-tech-fest/<p>Förra helgen var jag och Petter Ericsson och representerade <a href="https://umeahackerspace.se/">Umeå
Hackerspace</a> på <a href="http://musictechfest.org/">Music Tech
Fest</a>. Kort sagt kan man säga att det var
mycket trevligt folk, samt att vi vann pris för våran uppfunning: ett
enhandsinstrumentet vi döpte till
<a href="http://www.hackathon.io/projects/6915">Synthobon</a>. Kort sagt kan man
beskriva det som ett elektroniska brassinstrument …</p><p>Förra helgen var jag och Petter Ericsson och representerade <a href="https://umeahackerspace.se/">Umeå
Hackerspace</a> på <a href="http://musictechfest.org/">Music Tech
Fest</a>. Kort sagt kan man säga att det var
mycket trevligt folk, samt att vi vann pris för våran uppfunning: ett
enhandsinstrumentet vi döpte till
<a href="http://www.hackathon.io/projects/6915">Synthobon</a>. Kort sagt kan man
beskriva det som ett elektroniska brassinstrument. Just nu har vi lite
funderingar vad man kan göra med det i framtiden.</p>
<p>En kort video som visar instrumentet:</p>
<p>Lite bilder:</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/06/tmp_32138-DSC_00341353492899.jpg"><img alt="tmp_32138-DSC_00341353492899" src="../../../../../blog/wp-content/uploads/2015/06/tmp_32138-DSC_00341353492899-300x168.jpg"></a></p>
<p>Domare inspekterar Synthobonen i vårat bås</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/06/tmp_32138-DSC_0031-7289187.jpg"><img alt="tmp_32138-DSC_0031-7289187" src="../../../../../blog/wp-content/uploads/2015/06/tmp_32138-DSC_0031-7289187-300x168.jpg"></a></p>
<p>Närbild på anordningen</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/06/tmp_32138-DSC_0040993360719.jpg"><img alt="tmp_32138-DSC_0040993360719" src="../../../../../blog/wp-content/uploads/2015/06/tmp_32138-DSC_0040993360719-300x168.jpg"></a></p>
<p>MTF-deltagare i spacet efter efteråt, måndag</p>
<h1>Kommentarer</h1>
<p><strong>Anette Härdin</strong>, June 25, 2015 at 7:03 am</p>
<p>Vilken häftig grej. Funkar även för folk med båda händerna i behåll. Kan nog bli en storsäljare om ni kan marknadsföra den bra.</p>
<p><strong>tomas</strong>, July 1, 2015 at 7:42 pm</p>
<p>Jo, vi håller på att klura på det. Vi har skickat in en ansökan till OHMI – får se hur det går med den.</p>
<hr>
<p><strong>Anette Härdin</strong>, June 25, 2015 at 7:04 am</p>
<p>Man kan ju ha en på varje hand och bli en egen liten orkester ;-)</p>Mad Max: Fury Road2015-05-20T22:03:00+02:002015-05-20T22:03:00+02:00tomastag:www.härdin.se,2015-05-20:/blog/2015/05/20/mad-max-fury-road/<p><strong>2018 edit: I actually like this movie now, but I'm keeping this old article just because.
But you'll have to deal with the strikethrough!</strong></p>
<p><s>
Yesterday I went and saw the new Mad Max movie that's come out and I'm
going to write a few words about it. Beware that there …</s></p><p><strong>2018 edit: I actually like this movie now, but I'm keeping this old article just because.
But you'll have to deal with the strikethrough!</strong></p>
<p><s>
Yesterday I went and saw the new Mad Max movie that's come out and I'm
going to write a few words about it. Beware that there will be marked
spoilers in this post. View this as my own little version of <a href="https://www.youtube.com/playlist?list=PL34C1F26D03F5F9B8">Half in
the Bag</a>, but
suckier because it's text-only. Incidentally, they also did a <a href="https://www.youtube.com/watch?v=KP-6ewtJcdk&index=1&list=PL34C1F26D03F5F9B8">review of
Mad Max: Fury
Road</a>,
which disagrees with my views. Oh well, on with the post itself:</p>
<p>First of all, the main selling points of Fury Road: post-apocalyptic
vehicular desert action (action, action, action!). This is of course to
be expected with a Mad Max film, and it does deliver on that. There's
plenty of car chases, but also lots of interesting mechanical work and
prop work to look at. Most of the car chase scenes are real, done with
actual modified cars. All of the vehicles are have very interesting
designs, and the story works well enough.</p>
<p>But.</p>
<p>There's always a but. And in this case it's this: while Fury Road is
entertaining with lots of things to look at, it has some problems with
pacing. In order to explain this I'm first going to break the film down.</p>
<p><strong>WARNING: spoilers below</strong></p>
<p>The movie begins with Max being chased by what looks like raiders. They
throw explosives at his V8 Interceptor, causing it to flip over. Max is
then captured and brought to what we later learn is The Citadel, to be
used as an involuntary blood donor.</p>
<p>The Citadel is built inside two mountains on top of an aquifer and ruled
over by Immortan Joe and his many anemic(?) sons, who hoard the water in
order to control the poor who live on the ground below. Presumably they
maintain control mainly through gunpower, but Joe himself also controls
his children by taking on the role of a Norse preist or god. The general
structure of the Citadel is likely supposed to echo Bartertown. There's
even a tiny person!</p>
<p>The first half of the movie revolves around a water convoy lead by a
woman named Furiosa, sent by the Citadel to the nearby locations of Gas
Town and Bullet Farm. The convoy soon takes an unplanned detour, and we
learn that Furiosa is actually attempting to smuggle five of Joe's wives
to "the green place", the home from which she was kidnapped at a young
age. This results in a chase sequence that lasts the rest of the first
half of the movie. Max is brought along as a living blood bag for Nux,
one of Joe's sons.</p>
<p>After this chase sequence Furiosa, Max, Joe's escaped wives and Nux (who
chooses to defect) manage to make it to their destination, and join up
with the all-female remnants of Furiosa's tribe. We learn that the water
in "the green place" turned acid years ago, and that the tribe has been
forced to kill and scavange like everyone else ever since.</p>
<p>After some dithering Max convinces everyone to head back to the Citadel,
because the tribe has seeds from the time when they used to grow crops,
which the Citadel does not (what <em>they've</em> been eating for the last 20
years is anyone's guess). After once again being chased by Joe and his
men for most of the second half of the movie, Nux jams the tanker
they've been driving thus far into a narrow canyon, preventing Joe's
gang from following them. They also manage to kill Joe and steal his car
in the process. Max' old V8 manages to get destroyed as well, which is a
shame. Maybe it'll be back for the sequel, rising from the scrapheap
like a mechanical Pheonix!</p>
<p>Finally, what's left of our gang makes it back to the Citadel. Upon
finding it entirely unguarded Max unveils Joe's corpse strapped to the
hood the car, and the entire group is treated as liberators by everone
present, including Joe's anemic sons. Joe's men never make it back to
the Citadel, and everyone is happy, and they can grow crops with the old
tribe lady's seeds. Max winks at Furiosa and disappears into the crowd,
never to be seen again. The end!</p>
<p><strong>END OF SPOILERS</strong></p>
<p>Now this isn't a bad story in itself, even if there's some holes and
some things aren't explained in detail. A Mad Max film doesn't need a
complicated story. The problem is there's maybe 30 minutes of exposition
for the entire movie, and two one-hour blocks of non-stop action. Of
course, action is fun and exciting, but without much break time it gets
boring (for me at least). Such time could also be spent explaining
characters' motivation, backstory and so on. We're also thrown into the
first long action sequence almost immediately, with no explanation why
we should care. So yeah, this movie has some problems with pacing.</p>
<p>The second thing I'm going to complain about has to do a bit with tone.
Early in the film it is made clear that Joe's wives are basically sex
slaves. But they're shown scantily clad to titillate the audience, which
can perhaps be explained by them having recently escaped and being, you
know, sex slaves. What pushes it over the top though is when we get what
is basically a wet t-shirt scene the first time we see all of them in
one shot. That has to have been on purpose!</p>
<p>There's also a scene where six grown women are unable to wrestle down
two unarmed men. The Indian-looking wife who is surprisingly
knowledgeable about guns is interesting though.</p>
<p>On a positive note, the red-haired wife takes an interest in Nux when he
realizes Joe might be a bad guy. This brief scene provides some amount
of emotional depth, which I would have liked to see a bit more of. I
should note here that these two characters may be siblings, depending on
the precise nature of Joe's large, somewhat complicated family
situation.</p>
<p>Overall I'm a bit lukewarm about this movie. There's lots of action, the
stunts and props are really well made, but I expected a lot slower
pacing. Maybe I'm being unfair, but you know what?</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/05/dealwithit2.gif"><img alt="Deal with
it" src="../../../../../blog/wp-content/uploads/2015/05/dealwithit2.gif"></a>
</s></p>Bakdag2015-05-09T00:45:00+02:002015-05-09T00:45:00+02:00tomastag:www.härdin.se,2015-05-09:/blog/2015/05/09/bakdag/<p>Sista dagen på CodeMill -> bakdag. En enkel gräddtårta samt veganska
chokladbollar denna gång.</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/05/P5081568.jpg"><img alt="Tårtan!" src="../../../../../blog/wp-content/uploads/2015/05/P5081568-300x225.jpg"></a></p>
<p>Tårtan!</p>
<p>äsdsd</p>Laga jeans2015-05-04T21:33:00+02:002015-05-04T21:33:00+02:00tomastag:www.härdin.se,2015-05-04:/blog/2015/05/04/laga-jeans/<p>Tog mig tid att laga ett par jeans efter att ha fixat maskintråd nere på
stan. Kanske inte den mest vackraste lagningen någonsin, men det
fungerar och är bättre än att ha stora hål i knäna..</p>
<p>Märker även att matningen på symaskinen är lite skrotig, får försöka
skruva upp och …</p><p>Tog mig tid att laga ett par jeans efter att ha fixat maskintråd nere på
stan. Kanske inte den mest vackraste lagningen någonsin, men det
fungerar och är bättre än att ha stora hål i knäna..</p>
<p>Märker även att matningen på symaskinen är lite skrotig, får försöka
skruva upp och fixa någon dag.</p>
<p>Nu lite bilder:</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/05/P5041560.jpg"><img alt="OLYMPUS DIGITAL
CAMERA" src="../../../../../blog/wp-content/uploads/2015/05/P5041560-300x225.jpg"></a></p>
<p><a href="../../../../../blog/wp-content/uploads/2015/05/P5041561.jpg"><img alt="OLYMPUS DIGITAL
CAMERA" src="../../../../../blog/wp-content/uploads/2015/05/P5041561-300x225.jpg"></a></p>Back from Revision 20152015-04-08T23:18:00+02:002015-04-08T23:18:00+02:00tomastag:www.härdin.se,2015-04-08:/blog/2015/04/08/back-from-revision-2015/<p>Came back from this year's <a href="http://2015.revision-party.net/">Revision</a>
yesterday, time to write a bit about it.</p>
<p>The party plan was thus: write a simple NES demo and hold a seminar on
the <a href="http://ptscientists.com/blog/dropcontainer-RFP.html">lunar drop container
project</a> that <a href="http://scube.se/">me
and some other local people</a> are involved in.</p>
<p>I'd have to say that this …</p><p>Came back from this year's <a href="http://2015.revision-party.net/">Revision</a>
yesterday, time to write a bit about it.</p>
<p>The party plan was thus: write a simple NES demo and hold a seminar on
the <a href="http://ptscientists.com/blog/dropcontainer-RFP.html">lunar drop container
project</a> that <a href="http://scube.se/">me
and some other local people</a> are involved in.</p>
<p>I'd have to say that this year's Revision was much less stressful than
previous years, likely thanks to having most of work on the demo and the
seminar slides already done (disregarding the customary
just-before-deadline-panic-fixing). This left plenty of time for
socializing with old and new friends, and hanging out in the VIP area.</p>
<p>Food was better this year. In addition to the wurst and waffle stands
there was also Italian and vegan food! Quite nice.</p>
<p>As for the NES entry. the trickiest part was probably getting the sprite
compression and sync working. Perhaps there will be a post on that in
the future..</p>
<p>Finally, the seminar went quite well - I have a bunch of new interesting
contacts that I will have to follow up on. <a href="https://www.youtube.com/watch?v=hzzTYM-wIbg">Here's a link to the talk on
Revision's YouTube
channel</a>. I've also taken
the liberty of embedding it below:</p>
<p>I'm currently in the process of writing a more in-depth blog post about
the seminar and related things on the <a href="http://scube.se/blog/">scube
blog</a>.</p>
<p>Finally, some pictures:</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/04/P4031504.jpg"><img alt="Outside
Knoeki's" src="../../../../../blog/wp-content/uploads/2015/04/P4031504-300x225.jpg"></a></p>
<p>Outside Knoeki's place.</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/04/P4041506.jpg"><img alt="Dev shot
of our NES invite for
Nordlicht." src="../../../../../blog/wp-content/uploads/2015/04/P4041506-300x225.jpg"></a></p>
<p>Dev shot of our NES invite for Nordlicht.</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/04/P4041508.jpg"><img alt="Saturday
featured a lunar eclipse, but it was too cloudy to snap. Later the
clouds cleared a bit, but by then the eclipse was
over." src="../../../../../blog/wp-content/uploads/2015/04/P4041508-300x225.jpg"></a></p>
<p>Saturday featured a lunar eclipse, but it was too cloudy to snap. Later
the clouds cleared a bit, but by then the eclipse was over.</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/04/P4051514.jpg"><img alt="DSS
greeted in one of the 8k productions (I forget which
one)." src="../../../../../blog/wp-content/uploads/2015/04/P4051514-300x225.jpg"></a></p>
<p>DSS greeted in one of the 8k productions (I forget which
one).</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/04/P4051519.jpg"><img alt="8K
Reality. Quite a
crowdpleaser!" src="../../../../../blog/wp-content/uploads/2015/04/P4051519-300x225.jpg"></a></p>
<p>8K Reality. Quite a crowdpleaser!</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/04/P4051522.jpg"><img alt="Coke
Zero by JTZ and Skyrunner. A nice little 48 pixel vertical scroller for
the Atari VCS with plenty of cycle-counting going
on." src="../../../../../blog/wp-content/uploads/2015/04/P4051522-300x225.jpg"></a></p>
<p>Coke Zero by JTZ and Skyrunner. A nice little 48 pixel vertical scroller
for the Atari VCS with plenty of cycle-counting going on.</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/04/P4061525.jpg"><img alt="Shot of
the main hall from the organizer/VIP
area." src="../../../../../blog/wp-content/uploads/2015/04/P4061525-300x225.jpg"></a></p>
<p>Shot of the main hall from the organizer/VIP area.</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/04/P4061526.jpg"><img alt="Another
shot of the main
hall." src="../../../../../blog/wp-content/uploads/2015/04/P4061526-300x225.jpg"></a></p>
<p>Another shot of the main hall.</p>Demo pills 4 your brain2015-04-06T00:00:00+02:002015-04-06T00:00:00+02:00tomastag:www.härdin.se,2015-04-06:/demoscene/2015/04/06/demo-pills-4-your-brain/<p>Invite for Nordlicht 2015.
The most technically interesting thing about this one is the sprite compression used.
Parts of it was written in 6502 assembly, compared to <a href="http://www.härdin.se/demoscene/2013/09/07/ponies/">poNiES</a> which was written entirely in C.</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code><span class="n">Author</span><span class="o">:</span><span class="w"> </span><span class="n">Knoeki</span><span class="o">,</span><span class="w"> </span><span class="n">Tjoppen</span><span class="w"> </span><span class="n">and</span><span class="w"> </span><span class="n">visy</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="n">DSS</span>
<span class="n">Title</span><span class="o">:</span><span class="w"> </span><span class="n">Demo</span><span class="w"> </span><span class="n">pills</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="n">your</span><span class="w"> </span><span class="n">brain</span>
<span class="n">Compo</span><span class="o">:</span><span class="w"> </span><span class="n">Oldskool</span><span class="w"> </span><span class="n">Demo …</span></code></pre></div><p>Invite for Nordlicht 2015.
The most technically interesting thing about this one is the sprite compression used.
Parts of it was written in 6502 assembly, compared to <a href="http://www.härdin.se/demoscene/2013/09/07/ponies/">poNiES</a> which was written entirely in C.</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code><span class="n">Author</span><span class="o">:</span><span class="w"> </span><span class="n">Knoeki</span><span class="o">,</span><span class="w"> </span><span class="n">Tjoppen</span><span class="w"> </span><span class="n">and</span><span class="w"> </span><span class="n">visy</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="n">DSS</span>
<span class="n">Title</span><span class="o">:</span><span class="w"> </span><span class="n">Demo</span><span class="w"> </span><span class="n">pills</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="n">your</span><span class="w"> </span><span class="n">brain</span>
<span class="n">Compo</span><span class="o">:</span><span class="w"> </span><span class="n">Oldskool</span><span class="w"> </span><span class="n">Demo</span>
<span class="n">Platform</span><span class="o">:</span><span class="w"> </span><span class="n">Nintendo</span><span class="w"> </span><span class="n">Entertainment</span><span class="w"> </span><span class="n">System</span>
</code></pre></div>Leaving for Revision 20152015-04-02T07:56:00+02:002015-04-02T07:56:00+02:00tomastag:www.härdin.se,2015-04-02:/blog/2015/04/02/leaving-for-revision-2015/<p>Phone blogging sucks, but I'm all packed and ready to go!</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/04/tmp_21179-DSC_0001534914490.jpg"><img alt="tmp_21179-DSC_0001534914490" src="../../../../../blog/wp-content/uploads/2015/04/tmp_21179-DSC_0001534914490-300x168.jpg"></a></p>Scanning2015-03-12T22:39:00+01:002015-03-12T22:39:00+01:00tomastag:www.härdin.se,2015-03-12:/blog/2015/03/12/scanning/<p>Just a quick post to say that today I scanned some documents in Ubuntu
and it was a surprisingly smooth experience. Kudos to the developers of
the <a href="https://launchpad.net/simple-scan">"Simple Scan"</a> program. Makes me
wonder why printing is such a hassle >_<</p>House of Metal2015-03-02T21:40:00+01:002015-03-02T21:40:00+01:00tomastag:www.härdin.se,2015-03-02:/blog/2015/03/02/house-of-metal/<p>Just some pictures from <a href="http://houseofmetal.se/">House of Metal</a>, a
relatively large metal festival in town:</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/02/tmp_8703-DSC_01451017944687.jpg"><img alt="Finntroll" src="../../../../../blog/wp-content/uploads/2015/02/tmp_8703-DSC_01451017944687-300x168.jpg"></a></p>
<p><a href="http://www.finntroll-music.com/">Finntroll</a></p>
<p><a href="../../../../../blog/wp-content/uploads/2015/03/tmp_31178-DSC_01481017944687.jpg"><img alt="Unknown
band playing in the upstairs back
area" src="../../../../../blog/wp-content/uploads/2015/03/tmp_31178-DSC_01481017944687-300x168.jpg"></a></p>
<p>Unknown band playing in the upstairs back area</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/03/tmp_31178-DSC_0150-1132352008.jpg"><img alt="At The
Gates" src="../../../../../blog/wp-content/uploads/2015/03/tmp_31178-DSC_0150-1132352008-300x168.jpg"></a></p>
<p>At The Gates</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/03/tmp_31178-DSC_0154-288527395.jpg"><img alt="At The
Gates" src="../../../../../blog/wp-content/uploads/2015/03/tmp_31178-DSC_0154-288527395-300x168.jpg"></a></p>
<p>At The Gates</p>
<p>Tried to snap a short video of <a href="http://atthegates.se/">At The Gates</a>
playing, but clearly my phone isn't equipped to deal with that …</p><p>Just some pictures from <a href="http://houseofmetal.se/">House of Metal</a>, a
relatively large metal festival in town:</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/02/tmp_8703-DSC_01451017944687.jpg"><img alt="Finntroll" src="../../../../../blog/wp-content/uploads/2015/02/tmp_8703-DSC_01451017944687-300x168.jpg"></a></p>
<p><a href="http://www.finntroll-music.com/">Finntroll</a></p>
<p><a href="../../../../../blog/wp-content/uploads/2015/03/tmp_31178-DSC_01481017944687.jpg"><img alt="Unknown
band playing in the upstairs back
area" src="../../../../../blog/wp-content/uploads/2015/03/tmp_31178-DSC_01481017944687-300x168.jpg"></a></p>
<p>Unknown band playing in the upstairs back area</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/03/tmp_31178-DSC_0150-1132352008.jpg"><img alt="At The
Gates" src="../../../../../blog/wp-content/uploads/2015/03/tmp_31178-DSC_0150-1132352008-300x168.jpg"></a></p>
<p>At The Gates</p>
<p><a href="../../../../../blog/wp-content/uploads/2015/03/tmp_31178-DSC_0154-288527395.jpg"><img alt="At The
Gates" src="../../../../../blog/wp-content/uploads/2015/03/tmp_31178-DSC_0154-288527395-300x168.jpg"></a></p>
<p>At The Gates</p>
<p>Tried to snap a short video of <a href="http://atthegates.se/">At The Gates</a>
playing, but clearly my phone isn't equipped to deal with that kind of
volume:</p>
<video width="640" height="360" poster="../../../../../blog/wp-content/uploads/2015/03/tmp_31178-MOV_0152-529304227.jpg" controls style="max-width:100%"">
<source src="../../../../../blog/wp-content/uploads/2015/03/tmp_31178-MOV_0152-529304227.mp4" type="video/mp4"/>
<source src="../../../../../blog/wp-content/uploads/2015/03/tmp_31178-MOV_0152-529304227-2.webm" type="video/webm"/>
Your browser does not support the video tag :(
</video>First post2015-02-26T10:16:00+01:002015-02-26T10:16:00+01:00tomastag:www.härdin.se,2015-02-26:/blog/2015/02/26/first-post/<p>Putting something here to start off the new blog. I'll probably mostly
write about various hacks and local events. Post will probably alternate
between Swedish and English arbitrarily.</p>Call Now VCS2015-02-17T00:00:00+01:002015-02-17T00:00:00+01:00tomastag:www.härdin.se,2015-02-17:/demoscene/2015/02/17/call-now-vcs/<p>Pouet BBS nonsense.</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code>Call Now!!!
128 byte VCS version
By Tjoppen
Background: http://www.pouet.net/topic.php?which=10234&page=1
There are a total of six ROMs (three PAL, three NTSC):
callnow-[pal|ntsc].bin: The actual release, burn either to an EEPROM
callnow-harmony-[pal|ntsc].bin …</code></pre></div><p>Pouet BBS nonsense.</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code>Call Now!!!
128 byte VCS version
By Tjoppen
Background: http://www.pouet.net/topic.php?which=10234&page=1
There are a total of six ROMs (three PAL, three NTSC):
callnow-[pal|ntsc].bin: The actual release, burn either to an EEPROM
callnow-harmony-[pal|ntsc].bin: ROMs that work around a bug in the Harmony cartridge
callnow-stella-[pal|ntsc].bin: ROMs that work around a bug in Stella
This was mostly an opportunity to get line exact (as far as I can tell) sync working
</code></pre></div>Rave II2014-04-19T00:00:00+02:002014-04-19T00:00:00+02:00tomastag:www.härdin.se,2014-04-19:/demoscene/2014/04/19/rave-ii/<p>This has an evolution of the 3D renderer I did in <a href="http://www.härdin.se/demoscene/2013/12/27/the-ride-never-ends/">The Ride Never Ends</a>,
with the main innovation of faking semi-trasparency via dithering.
I may have done some other things in it as well, I don't quite recall.</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code><span class="n">Rave</span><span class="w"> </span><span class="n">II</span>
<span class="n">A</span><span class="w"> </span><span class="n">mIRC</span><span class="w"> </span><span class="n">demo</span><span class="w"> </span><span class="n">by</span><span class="w"> </span><span class="n">Digital</span><span class="w"> </span><span class="n">Sounds</span><span class="w"> </span><span class="n">System</span>
<span class="o">--------------------------------------</span>
<span class="n">sorry …</span></code></pre></div><p>This has an evolution of the 3D renderer I did in <a href="http://www.härdin.se/demoscene/2013/12/27/the-ride-never-ends/">The Ride Never Ends</a>,
with the main innovation of faking semi-trasparency via dithering.
I may have done some other things in it as well, I don't quite recall.</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code><span class="n">Rave</span><span class="w"> </span><span class="n">II</span>
<span class="n">A</span><span class="w"> </span><span class="n">mIRC</span><span class="w"> </span><span class="n">demo</span><span class="w"> </span><span class="n">by</span><span class="w"> </span><span class="n">Digital</span><span class="w"> </span><span class="n">Sounds</span><span class="w"> </span><span class="n">System</span>
<span class="o">--------------------------------------</span>
<span class="n">sorry</span><span class="p">,</span><span class="w"> </span><span class="n">we</span><span class="w"> </span><span class="n">were</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">fucking</span><span class="w"> </span><span class="n">rush</span>
<span class="n">serves</span><span class="w"> </span><span class="n">me</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">trying</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">make</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">demo</span>
<span class="ow">in</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="n">weeks</span><span class="w"> </span><span class="n">every</span><span class="w"> </span><span class="n">time</span><span class="o">.</span>
<span class="o">--------------------------------------</span>
<span class="n">Instructions</span><span class="p">:</span>
<span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="n">get</span><span class="w"> </span><span class="n">mIRC</span><span class="w"> </span><span class="mf">3.65</span><span class="p">:</span><span class="w"> </span><span class="n">http</span><span class="p">:</span><span class="o">//</span><span class="n">www</span><span class="o">.</span><span class="n">mirc</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">get</span><span class="o">.</span><span class="n">php</span><span class="err">?</span><span class="n">version</span><span class="o">=</span><span class="mi">635</span>
<span class="w"> </span><span class="p">(</span><span class="ow">and</span><span class="w"> </span><span class="n">run</span><span class="w"> </span><span class="n">it</span><span class="p">)</span>
<span class="mi">2</span><span class="p">)</span><span class="w"> </span><span class="n">type</span><span class="p">:</span><span class="w"> </span><span class="o">/</span><span class="nb">load</span><span class="w"> </span><span class="o">-</span><span class="n">rs</span><span class="w"> </span><span class="n">path</span>\<span class="n">to</span>\<span class="n">rave2</span>\<span class="n">demo</span><span class="o">.</span><span class="n">mrc</span>
<span class="w"> </span><span class="p">(</span><span class="n">be</span><span class="w"> </span><span class="n">sure</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">allow</span><span class="w"> </span><span class="n">it</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">initialize</span><span class="p">)</span>
<span class="mi">3</span><span class="p">)</span><span class="w"> </span><span class="n">Run</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">demo</span><span class="w"> </span><span class="n">with</span><span class="p">:</span><span class="w"> </span><span class="o">/</span><span class="n">rave2</span>
<span class="w"> </span><span class="p">(</span><span class="n">it</span><span class="s1">'ll always open in full screen)</span>
<span class="mi">4</span><span class="p">)</span><span class="w"> </span><span class="n">Move</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">mouse</span><span class="w"> </span><span class="n">cursor</span><span class="w"> </span><span class="n">outta</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">way</span><span class="p">,</span><span class="w"> </span><span class="n">sit</span><span class="w"> </span><span class="n">back</span><span class="p">,</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">enjoy</span><span class="o">!</span>
<span class="o">--------------------------------------</span>
<span class="n">In</span><span class="w"> </span><span class="n">case</span><span class="w"> </span><span class="n">something</span><span class="w"> </span><span class="n">fucks</span><span class="w"> </span><span class="n">up</span><span class="p">,</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">first</span><span class="w"> </span><span class="n">thing</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">can</span><span class="w"> </span><span class="n">try</span>
<span class="k">is</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">unload</span><span class="w"> </span><span class="n">all</span><span class="w"> </span><span class="n">scripts</span><span class="p">:</span>
<span class="o">//</span><span class="k">var</span><span class="w"> </span><span class="o">%</span><span class="n">x</span><span class="w"> </span><span class="o">$</span><span class="n">script</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="o">%</span><span class="n">x</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">unload</span><span class="w"> </span><span class="o">-</span><span class="n">rs</span><span class="w"> </span><span class="o">$</span><span class="n">qt</span><span class="p">(</span><span class="o">$</span><span class="n">script</span><span class="p">(</span><span class="o">%</span><span class="n">x</span><span class="p">))</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">dec</span><span class="w"> </span><span class="o">%</span><span class="n">x</span><span class="w"> </span><span class="p">}</span>
<span class="ow">and</span><span class="w"> </span><span class="n">then</span><span class="w"> </span><span class="n">re</span><span class="o">-</span><span class="n">try</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="n">step</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">instructions</span><span class="o">.</span>
<span class="n">In</span><span class="w"> </span><span class="n">case</span><span class="w"> </span><span class="n">there</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">no</span><span class="w"> </span><span class="n">sound</span><span class="p">,</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">may</span><span class="w"> </span><span class="n">have</span><span class="w"> </span><span class="n">sounds</span><span class="w"> </span><span class="n">disabled</span><span class="o">.</span><span class="w"> </span><span class="n">To</span><span class="w"> </span><span class="n">fix</span><span class="w"> </span><span class="n">this</span><span class="p">:</span>
<span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="n">press</span><span class="w"> </span><span class="n">alt</span><span class="o">+</span><span class="n">o</span>
<span class="mi">2</span><span class="p">)</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="s2">"Sounds"</span><span class="w"> </span><span class="n">tab</span>
<span class="mi">3</span><span class="p">)</span><span class="w"> </span><span class="n">check</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="s2">"Enable sounds"</span><span class="w"> </span><span class="n">box</span>
</code></pre></div>The Ride Never Ends2013-12-27T00:00:00+01:002013-12-27T00:00:00+01:00tomastag:www.härdin.se,2013-12-27:/demoscene/2013/12/27/the-ride-never-ends/<p>I did the 3D in this one if memory serves me right.
First the lines are drawn, then the shading is done with flood fills.</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code><span class="n">bla</span><span class="w"> </span><span class="n">bla</span><span class="w"> </span><span class="n">bla</span><span class="w"> </span><span class="n">demo</span><span class="w"> </span><span class="n">by</span><span class="w"> </span><span class="n">DSS</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">know</span><span class="w"> </span><span class="n">what</span><span class="w"> </span><span class="n">this</span><span class="w"> </span><span class="k">is</span>
<span class="nb">load</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="o">/</span><span class="nb">load</span><span class="w"> </span><span class="o">-</span><span class="n">rs</span><span class="w"> </span>\<span class="n">path</span>\<span class="n">to</span>\<span class="n">demo</span><span class="o">.</span><span class="n">mrc</span>
<span class="n">allow</span><span class="w"> </span><span class="n">initialization</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">asked</span><span class="o">.</span>
<span class="n">run …</span></code></pre></div><p>I did the 3D in this one if memory serves me right.
First the lines are drawn, then the shading is done with flood fills.</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code><span class="n">bla</span><span class="w"> </span><span class="n">bla</span><span class="w"> </span><span class="n">bla</span><span class="w"> </span><span class="n">demo</span><span class="w"> </span><span class="n">by</span><span class="w"> </span><span class="n">DSS</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">know</span><span class="w"> </span><span class="n">what</span><span class="w"> </span><span class="n">this</span><span class="w"> </span><span class="k">is</span>
<span class="nb">load</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="o">/</span><span class="nb">load</span><span class="w"> </span><span class="o">-</span><span class="n">rs</span><span class="w"> </span>\<span class="n">path</span>\<span class="n">to</span>\<span class="n">demo</span><span class="o">.</span><span class="n">mrc</span>
<span class="n">allow</span><span class="w"> </span><span class="n">initialization</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">asked</span><span class="o">.</span>
<span class="n">run</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="o">/</span><span class="n">trne</span><span class="w"> </span><span class="n">fs</span>
<span class="n">preferably</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">mIRC</span><span class="w"> </span><span class="mf">6.35</span>
<span class="n">don</span><span class="s1">'t forget to move the mouse out of the way :3</span>
</code></pre></div>poNiES2013-09-07T00:00:00+02:002013-09-07T00:00:00+02:00tomastag:www.härdin.se,2013-09-07:/demoscene/2013/09/07/ponies/<p>Made during the pony craze of the early 2010's.
Very glitchy due to how temperamental the NES PPU is,
which was initially unintended.
But as often with these things, we decided to leave it in :)
Pure C, very little optimization attempted.
This taught us that cc65 is basically garbage(!)</p>aTaRSI2013-07-20T00:00:00+02:002013-07-20T00:00:00+02:00tomastag:www.härdin.se,2013-07-20:/demoscene/2013/07/20/atarsi/<p>I was asked to do the music for this one, which is not really my forte.
It ended up winning anyway, but I am not pleased with it..
This was before <a href="http://atariage.com/forums/topic/250014-tiatracker-a-new-sound-routine-and-sequencer-application/">TIATracker</a> existed,
in the dark old days of composing VCS music by editing tables in assembly.</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code>aTaRSI
The …</code></pre></div><p>I was asked to do the music for this one, which is not really my forte.
It ended up winning anyway, but I am not pleased with it..
This was before <a href="http://atariage.com/forums/topic/250014-tiatracker-a-new-sound-routine-and-sequencer-application/">TIATracker</a> existed,
in the dark old days of composing VCS music by editing tables in assembly.</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code>aTaRSI
The first 2600 demo by TRSi, DSS and Crest with a guest appearance by Onslaught
32K ROM with F4 bankswitching
</code></pre></div>Spectrum2013-05-11T00:00:00+02:002013-05-11T00:00:00+02:00tomastag:www.härdin.se,2013-05-11:/demoscene/2013/05/11/spectrum/<p>An mIRC invitro for Nordlicht 2013.
First time I ever coded something graphical for mIRC,
something which I had no idea was even possible.
Very quirky platform!</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="n">SPECTRUM</span>
<span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="n">Nordlicht</span><span class="w"> </span><span class="n">Invite</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">mIRC</span><span class="w"> </span><span class="k">by</span><span class="w"> </span><span class="n">Digital</span><span class="w"> </span><span class="k">Sounds</span><span class="w"> </span><span class="k">System</span>
<span class="w"> </span><span class="k">Load</span><span class="w"> </span><span class="k">with</span>
<span class="w"> </span><span class="o">/</span><span class="k">load</span><span class="w"> </span><span class="o">-</span><span class="n">rs</span><span class="w"> </span><span class="err">\</span><span class="k">path</span><span class="err">\</span><span class="k">to</span><span class="err">\</span><span class="n">spectrum</span><span class="p">.</span><span class="n">mrc</span>
<span class="w"> </span><span class="n">run</span><span class="w"> </span><span class="k">with</span><span class="o">:</span>
<span class="w"> </span><span class="o">/</span><span class="n">spectrum</span><span class="w"> </span><span class="n">fs …</span></code></pre></div><p>An mIRC invitro for Nordlicht 2013.
First time I ever coded something graphical for mIRC,
something which I had no idea was even possible.
Very quirky platform!</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="n">SPECTRUM</span>
<span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="n">Nordlicht</span><span class="w"> </span><span class="n">Invite</span><span class="w"> </span><span class="k">on</span><span class="w"> </span><span class="n">mIRC</span><span class="w"> </span><span class="k">by</span><span class="w"> </span><span class="n">Digital</span><span class="w"> </span><span class="k">Sounds</span><span class="w"> </span><span class="k">System</span>
<span class="w"> </span><span class="k">Load</span><span class="w"> </span><span class="k">with</span>
<span class="w"> </span><span class="o">/</span><span class="k">load</span><span class="w"> </span><span class="o">-</span><span class="n">rs</span><span class="w"> </span><span class="err">\</span><span class="k">path</span><span class="err">\</span><span class="k">to</span><span class="err">\</span><span class="n">spectrum</span><span class="p">.</span><span class="n">mrc</span>
<span class="w"> </span><span class="n">run</span><span class="w"> </span><span class="k">with</span><span class="o">:</span>
<span class="w"> </span><span class="o">/</span><span class="n">spectrum</span><span class="w"> </span><span class="n">fs</span>
<span class="w"> </span><span class="p">(</span><span class="w"> </span><span class="k">remove</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n n-Quoted">`fs`</span><span class="w"> </span><span class="k">option</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">rather</span><span class="w"> </span><span class="n">have</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">tiny</span>
<span class="w"> </span><span class="n">ass</span><span class="w"> </span><span class="k">window</span><span class="w"> </span><span class="k">to</span><span class="w"> </span><span class="n">watch</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">demo</span><span class="w"> </span><span class="k">in</span><span class="p">...</span><span class="w"> </span><span class="p">..</span><span class="w"> </span><span class="p">.</span><span class="w"> </span><span class="p">)</span>
<span class="w"> </span><span class="n">Partycoding</span><span class="w"> </span><span class="n">ftw</span><span class="p">.</span>
</code></pre></div>Sicktro2013-03-13T00:00:00+01:002013-03-13T00:00:00+01:00tomastag:www.härdin.se,2013-03-13:/demoscene/2013/03/13/sicktro/<p>Only three entries in oldskool intro this year, so 2nd place wasn't terribly impressive.</p>SillyVenture 2k12 invitro2012-10-26T00:00:00+02:002012-10-26T00:00:00+02:00tomastag:www.härdin.se,2012-10-26:/demoscene/2012/10/26/sillyventure-2k12-invitro/<p>This one was quite fun to write,
since it features a little animation with Pitfall Harry kicking the screen to get a logo to descend.
The main effect is a variant of the tried and tested fullscreen plasma, but with XOR instead of additions to make up the pixel values …</p><p>This one was quite fun to write,
since it features a little animation with Pitfall Harry kicking the screen to get a logo to descend.
The main effect is a variant of the tried and tested fullscreen plasma, but with XOR instead of additions to make up the pixel values.
It also features Huffman based text compression,
and packs part of the text data into the font data.
Finally, it seems to have started a minor trend with having Pitfall Harry in Atari invites, see <a href="https://www.pouet.net/prod.php?which=76251">Lapin Kulta by Dentifrice</a>.</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="n">SillyVenture</span><span class="w"> </span><span class="mi">2</span><span class="n">k12</span>
<span class="n">Invitro</span><span class="w"> </span><span class="n">by</span><span class="w"> </span><span class="n">these</span><span class="w"> </span><span class="n">fine</span><span class="w"> </span><span class="n">gentlemen</span><span class="p">:</span>
<span class="w"> </span><span class="n">Code</span><span class="o">/</span><span class="n">GFX</span><span class="p">:</span><span class="w"> </span><span class="n">Tjoppen</span><span class="o">^</span><span class="n">DSS</span>
<span class="n">Invite</span><span class="w"> </span><span class="n">text</span><span class="p">:</span><span class="w"> </span><span class="n">Grey</span><span class="o">/</span><span class="n">MSB</span>
<span class="w"> </span><span class="n">Music</span><span class="p">:</span><span class="w"> </span><span class="n">Jakub</span><span class="w"> </span><span class="n">Husak</span>
<span class="n">For</span><span class="w"> </span><span class="n">scroller</span><span class="w"> </span><span class="n">text</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="n">party</span><span class="w"> </span><span class="n">details</span><span class="p">,</span><span class="w"> </span><span class="n">see</span><span class="w"> </span><span class="n">sv2k12</span><span class="o">.</span><span class="n">nfo</span><span class="o">.</span>
<span class="n">Programming</span><span class="w"> </span><span class="n">notes</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="n">Tjoppen</span><span class="p">,</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">those</span><span class="w"> </span><span class="n">interested</span><span class="p">:</span>
<span class="n">The</span><span class="w"> </span><span class="n">text</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">Huffman</span><span class="w"> </span><span class="n">encoded</span><span class="p">,</span><span class="w"> </span><span class="n">which</span><span class="w"> </span><span class="n">saves</span><span class="w"> </span><span class="n">quite</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">bit</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">space</span><span class="o">.</span>
<span class="n">After</span><span class="w"> </span><span class="n">getting</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">compressor</span><span class="p">,</span><span class="w"> </span><span class="n">decompressor</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">text</span><span class="w"> </span><span class="n">kernel</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">work</span><span class="w"> </span><span class="n">I</span><span class="w"> </span><span class="n">realized</span>
<span class="n">that</span><span class="w"> </span><span class="n">none</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">glyphs</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">font</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">rightmost</span><span class="w"> </span><span class="n">two</span><span class="w"> </span><span class="n">pixels</span><span class="o">.</span><span class="w"> </span><span class="n">This</span><span class="w"> </span><span class="n">meant</span>
<span class="n">that</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">these</span><span class="w"> </span><span class="n">bits</span><span class="w"> </span><span class="n">could</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">masked</span><span class="w"> </span><span class="n">off</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">kernel</span><span class="w"> </span><span class="n">then</span><span class="w"> </span><span class="n">that</span><span class="w"> </span><span class="n">space</span><span class="w"> </span><span class="n">could</span><span class="w"> </span><span class="n">be</span>
<span class="n">used</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">other</span><span class="w"> </span><span class="n">purposes</span><span class="o">.</span>
<span class="n">Luckily</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">SAX</span><span class="w"> </span><span class="n">instruction</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">well</span><span class="w"> </span><span class="n">suited</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">this</span><span class="w"> </span><span class="n">task</span><span class="w"> </span><span class="n">when</span><span class="w"> </span><span class="n">X</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">loaded</span><span class="w"> </span><span class="n">with</span><span class="w"> </span><span class="n">a</span>
<span class="n">suitable</span><span class="w"> </span><span class="n">mask</span><span class="p">,</span><span class="w"> </span><span class="n">meaning</span><span class="w"> </span><span class="n">this</span><span class="w"> </span><span class="n">space</span><span class="w"> </span><span class="n">was</span><span class="w"> </span><span class="n">indeed</span><span class="w"> </span><span class="n">freed</span><span class="o">.</span>
<span class="n">In</span><span class="w"> </span><span class="n">other</span><span class="w"> </span><span class="n">words</span><span class="p">,</span><span class="w"> </span><span class="n">part</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">Huffman</span><span class="w"> </span><span class="n">coded</span><span class="w"> </span><span class="n">text</span><span class="w"> </span><span class="n">data</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">stored</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">font</span>
<span class="n">glyphs</span><span class="p">,</span><span class="w"> </span><span class="n">which</span><span class="w"> </span><span class="n">saves</span><span class="w"> </span><span class="n">two</span><span class="w"> </span><span class="n">bytes</span><span class="w"> </span><span class="n">per</span><span class="w"> </span><span class="n">glyphs</span><span class="w"> </span><span class="p">(</span><span class="mi">2</span><span class="o">*</span><span class="mi">8</span><span class="w"> </span><span class="n">bits</span><span class="p">)</span><span class="o">.</span>
</code></pre></div>Prost2012-08-13T00:00:00+02:002012-08-13T00:00:00+02:00tomastag:www.härdin.se,2012-08-13:/demoscene/2012/08/13/prost/<p>Can't go wrong with a beer theme :)</p>hectoByte2012-08-10T00:00:00+02:002012-08-10T00:00:00+02:00tomastag:www.härdin.se,2012-08-10:/demoscene/2012/08/10/hectobyte/<p>Tried to get as much variation as possible into a 128 byte entry.
A respectable 2nd place, considering fsqrt was in the compo (and won).</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="n">hectoByte</span>
<span class="w"> </span><span class="n">by</span><span class="w"> </span><span class="n">Tjoppen</span><span class="o">^</span><span class="n">DSS</span>
<span class="w"> </span><span class="o">~~</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="n">VCS</span><span class="w"> </span><span class="n">intro</span><span class="w"> </span><span class="n">needs</span><span class="w"> </span><span class="n">neither</span><span class="w"> </span><span class="n">VSYNC</span><span class="w"> </span><span class="n">nor</span><span class="w"> </span><span class="n">proper</span><span class="w"> </span><span class="n">interrupt</span><span class="w"> </span><span class="n">vectors</span><span class="w"> </span><span class="o">~~</span>
<span class="w"> </span><span class="n">Works</span><span class="w"> </span><span class="n">best</span><span class="w"> </span><span class="n">when</span><span class="w"> </span><span class="n">run</span><span class="w"> </span><span class="n">on</span><span class="w"> </span><span class="n">real</span><span class="w"> </span><span class="n">hardware</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">hooked</span><span class="w"> </span><span class="n">up …</span></code></pre></div><p>Tried to get as much variation as possible into a 128 byte entry.
A respectable 2nd place, considering fsqrt was in the compo (and won).</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="n">hectoByte</span>
<span class="w"> </span><span class="n">by</span><span class="w"> </span><span class="n">Tjoppen</span><span class="o">^</span><span class="n">DSS</span>
<span class="w"> </span><span class="o">~~</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="n">VCS</span><span class="w"> </span><span class="n">intro</span><span class="w"> </span><span class="n">needs</span><span class="w"> </span><span class="n">neither</span><span class="w"> </span><span class="n">VSYNC</span><span class="w"> </span><span class="n">nor</span><span class="w"> </span><span class="n">proper</span><span class="w"> </span><span class="n">interrupt</span><span class="w"> </span><span class="n">vectors</span><span class="w"> </span><span class="o">~~</span>
<span class="w"> </span><span class="n">Works</span><span class="w"> </span><span class="n">best</span><span class="w"> </span><span class="n">when</span><span class="w"> </span><span class="n">run</span><span class="w"> </span><span class="n">on</span><span class="w"> </span><span class="n">real</span><span class="w"> </span><span class="n">hardware</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">hooked</span><span class="w"> </span><span class="n">up</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">forgiving</span><span class="w"> </span><span class="n">TV</span><span class="p">,</span>
<span class="n">loaded</span><span class="w"> </span><span class="n">onto</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">Harmony</span><span class="w"> </span><span class="n">cart</span><span class="s1">'s EEPROM ("harmonycart hectoByte.bin" using the CLI)</span>
<span class="w"> </span><span class="n">In</span><span class="w"> </span><span class="n">Stella</span><span class="p">,</span><span class="w"> </span><span class="n">run</span><span class="w"> </span><span class="n">hectoByte</span><span class="o">-</span><span class="n">stella</span><span class="o">.</span><span class="n">bin</span><span class="w"> </span><span class="ow">or</span><span class="w"> </span><span class="n">it</span><span class="w"> </span><span class="n">runs</span><span class="w"> </span><span class="n">at</span><span class="w"> </span><span class="n">incorrect</span><span class="w"> </span><span class="n">speed</span>
<span class="w"> </span><span class="n">The</span><span class="w"> </span><span class="n">Harmony</span><span class="w"> </span><span class="n">menu</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">MESS</span><span class="w"> </span><span class="n">don</span><span class="s1">'t support 128 B - use hectoByte-4k.bin instead</span>
<span class="w"> </span><span class="n">Released</span><span class="w"> </span><span class="n">at</span><span class="w"> </span><span class="n">Outline</span><span class="w"> </span><span class="mi">2012</span>
</code></pre></div>Sound Coder2012-05-19T00:00:00+02:002012-05-19T00:00:00+02:00tomastag:www.härdin.se,2012-05-19:/demoscene/2012/05/19/sound-coder/<p>A sound codec experiment, using a kind of 1-bit ADPCM thing.
Doesn't bother with VSYNC, so won't play properly on older versions of Stella and z26.</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code><span class="nv">Sound</span><span class="w"> </span><span class="nv">Coder</span><span class="w"> </span><span class="nv">by</span><span class="w"> </span><span class="nv">DSS</span>
<span class="nv">A</span><span class="w"> </span><span class="mi">32</span><span class="nv">k</span><span class="w"> </span><span class="nv">sound</span><span class="w"> </span><span class="nv">codec</span><span class="w"> </span><span class="nv">demo</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nv">the</span><span class="w"> </span><span class="nv">Atari</span><span class="w"> </span><span class="mi">2600</span><span class="w"> </span><span class="nv">VCS</span>
<span class="nv">Released</span><span class="w"> </span><span class="nv">at</span><span class="w"> </span><span class="nv">Stream</span><span class="w"> </span><span class="mi">2012</span>
<span class="nv">Code</span><span class="w"> </span><span class="nv">by</span><span class="w"> </span><span class="nv">Tjoppen</span>
<span class="nv">Music …</span></code></pre></div><p>A sound codec experiment, using a kind of 1-bit ADPCM thing.
Doesn't bother with VSYNC, so won't play properly on older versions of Stella and z26.</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code><span class="nv">Sound</span><span class="w"> </span><span class="nv">Coder</span><span class="w"> </span><span class="nv">by</span><span class="w"> </span><span class="nv">DSS</span>
<span class="nv">A</span><span class="w"> </span><span class="mi">32</span><span class="nv">k</span><span class="w"> </span><span class="nv">sound</span><span class="w"> </span><span class="nv">codec</span><span class="w"> </span><span class="nv">demo</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nv">the</span><span class="w"> </span><span class="nv">Atari</span><span class="w"> </span><span class="mi">2600</span><span class="w"> </span><span class="nv">VCS</span>
<span class="nv">Released</span><span class="w"> </span><span class="nv">at</span><span class="w"> </span><span class="nv">Stream</span><span class="w"> </span><span class="mi">2012</span>
<span class="nv">Code</span><span class="w"> </span><span class="nv">by</span><span class="w"> </span><span class="nv">Tjoppen</span>
<span class="nv">Music</span><span class="w"> </span><span class="nv">by</span><span class="w"> </span><span class="nv">Knoeki</span>
<span class="nv">Use</span><span class="w"> </span><span class="nv">proper</span><span class="w"> </span><span class="nv">hardware</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nv">neither</span><span class="w"> </span><span class="nv">Stella</span><span class="w"> </span><span class="nv">nor</span><span class="w"> </span><span class="nv">z26</span><span class="w"> </span><span class="nv">handles</span><span class="w"> </span><span class="nv">this</span><span class="w"> </span><span class="nv">correctly</span>
</code></pre></div>Self portrait2012-04-08T00:00:00+02:002012-04-08T00:00:00+02:00tomastag:www.härdin.se,2012-04-08:/demoscene/2012/04/08/self-portrait/<p>Disqualified because pure graphics conversions were not allowed.</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code><span class="gh">Self Portrait by Tjoppen</span>
<span class="gh">------------------------</span>
A multi-color 18x75 fullscreen bitmap in 4 KiB on the Atari 2600 VCS.
Each line has a separate 2-bit palette.
Released at Revision 2012.
Source code included - feel free to play around with it :)
Fun things to …</code></pre></div><p>Disqualified because pure graphics conversions were not allowed.</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code><span class="gh">Self Portrait by Tjoppen</span>
<span class="gh">------------------------</span>
A multi-color 18x75 fullscreen bitmap in 4 KiB on the Atari 2600 VCS.
Each line has a separate 2-bit palette.
Released at Revision 2012.
Source code included - feel free to play around with it :)
Fun things to do include creating an NTSC port.
<span class="gh">Other VCS stuff by me</span>
<span class="gh">---------------------</span>
See http://pouet.net/groups.php?which=11387
</code></pre></div>Skjutpung2012-04-08T00:00:00+02:002012-04-08T00:00:00+02:00tomastag:www.härdin.se,2012-04-08:/demoscene/2012/04/08/skjutpung/<p>A pong clone where you can shoot your opponent!
And a quick partyhack that follows the demoscene tradition of immature names (compare <a href="http://www.slengpung.com/">slengpung.com</a>).</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code> <span class="n">Skjutpung</span>
<span class="n">by</span> <span class="n">Tjoppen</span> <span class="o">and</span> <span class="n">Tony</span> <span class="n">Akano</span>
<span class="n">Released</span> <span class="nb">at</span> <span class="n">Revision</span> <span class="mi">2012</span>
-------------------------
<span class="n">The</span> <span class="nb">result</span> <span class="nb">of</span> <span class="n">waking</span> <span class="n">up</span> <span class="n">two</span> <span class="n">hours</span> <span class="o">before</span> <span class="n">the</span> <span class="n">game</span> <span class="n">compo</span> <span class="n">deadline</span> :)
<span class="n">It's</span> <span class="n">a …</span></code></pre></div><p>A pong clone where you can shoot your opponent!
And a quick partyhack that follows the demoscene tradition of immature names (compare <a href="http://www.slengpung.com/">slengpung.com</a>).</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code> <span class="n">Skjutpung</span>
<span class="n">by</span> <span class="n">Tjoppen</span> <span class="o">and</span> <span class="n">Tony</span> <span class="n">Akano</span>
<span class="n">Released</span> <span class="nb">at</span> <span class="n">Revision</span> <span class="mi">2012</span>
-------------------------
<span class="n">The</span> <span class="nb">result</span> <span class="nb">of</span> <span class="n">waking</span> <span class="n">up</span> <span class="n">two</span> <span class="n">hours</span> <span class="o">before</span> <span class="n">the</span> <span class="n">game</span> <span class="n">compo</span> <span class="n">deadline</span> :)
<span class="n">It's</span> <span class="n">a</span> <span class="n">pong</span> <span class="nb">clone</span> <span class="k">for</span> <span class="n">the</span> <span class="n">Atari</span> <span class="mi">2600</span> <span class="n">VCS</span>,
<span class="k">with</span> <span class="n">the</span> <span class="n">addition</span> <span class="nb">of</span> <span class="n">being</span> <span class="n">able</span> <span class="nb">to</span> <span class="n">fire</span> <span class="n">missiles</span>.
<span class="n">Use</span> <span class="n">the</span> <span class="n">Color</span><span class="o">/</span><span class="n">BW</span> <span class="n">switch</span> <span class="nb">to</span> <span class="n">switch</span> <span class="n">between</span> <span class="n">PAL</span><span class="o">/</span><span class="n">NTSC</span>.
<span class="n">Fairly</span> <span class="n">buggy</span>, <span class="n">such</span> <span class="n">as:</span>
* <span class="n">The</span> <span class="n">game</span> <span class="k">does</span> <span class="nb">not</span> <span class="n">stop</span> <span class="nb">after</span> <span class="n">four</span> <span class="n">wins</span> (<span class="n">the</span> <span class="n">planned</span> <span class="nb">max</span> <span class="n">score</span>)
* <span class="n">Holding</span> <span class="n">either</span> <span class="n">paddle</span> <span class="n">button</span> <span class="n">down</span> <span class="n">results</span> <span class="nb">in</span> <span class="n">the</span> <span class="n">missiles</span> <span class="n">behaving</span> <span class="n">strange</span>
* <span class="n">Reset</span> <span class="k">does</span> <span class="nb">not</span> <span class="n">work</span> - <span class="n">you</span> <span class="n">have</span> <span class="nb">to</span> <span class="n">manually</span> <span class="n">restart</span> <span class="n">the</span> <span class="n">console</span>
* <span class="n">Bounce</span> <span class="n">sound</span> <span class="n">effect</span> <span class="k">does</span> <span class="nb">not</span> <span class="n">work</span>
<span class="n">Game</span> <span class="n">logic</span>, <span class="n">kernel</span> <span class="n">etc</span>. <span class="n">by</span> <span class="n">Tjoppen</span>
<span class="n">Sound</span> <span class="n">effects</span> <span class="n">by</span> <span class="n">Tony</span> <span class="n">Akano</span>
<span class="n">Source</span> <span class="nb">code</span> <span class="n">included</span>, <span class="k">for</span> <span class="n">you</span> <span class="n">brave</span> <span class="n">souls</span>.
<span class="n">For</span> <span class="n">Tjoppen's</span> <span class="n">current</span> <span class="o">and</span> <span class="n">future</span> <span class="n">prods</span>, <span class="n">see</span>
<span class="n">http:</span>//<span class="n">pouet</span>.<span class="n">net</span><span class="o">/</span><span class="n">groups</span>.<span class="n">php</span><span class="o">?</span><span class="n">which</span>=<span class="mi">11387</span>
<span class="n">Mail:</span> <span class="n">tjoppen</span> <span class="nb">at</span> <span class="n">gamedev</span> <span class="n">dot</span> <span class="n">se</span>
</code></pre></div>
<p>Note that I have change e-mail since then.</p>Stella Lives!2012-04-08T00:00:00+02:002012-04-08T00:00:00+02:00tomastag:www.härdin.se,2012-04-08:/demoscene/2012/04/08/stella-lives/<p>I won the compo with this one, much to my surprise.
It has a more refined plasma than the one in Minute and a Bit.
I had originally intended to tell a story critical of transhumanism with it, but I couldn't figure out how to do that effectively.
So it …</p><p>I won the compo with this one, much to my surprise.
It has a more refined plasma than the one in Minute and a Bit.
I had originally intended to tell a story critical of transhumanism with it, but I couldn't figure out how to do that effectively.
So it ended up being a tech demo instead!</p>
<p>This prod and <a href="http://www.härdin.se/demoscene/2011/11/09/minute-and-a-bit/">Minute and a Bit</a> are both included in the Scene Demos 6-in-1 cartridge by SvOlli (<a href="https://www.pouet.net/prod.php?which=61318">pouet.net</a>, <a href="https://demozoo.org/productions/98009/">demozoo.com</a>, <a href="http://xayax.net/nonxayax/scene_demos_6-in-1/">xayax.net</a>).</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="nv">Stella</span><span class="w"> </span><span class="nv">Lives</span><span class="o">!</span>
<span class="w"> </span><span class="nv">by</span><span class="w"> </span><span class="nv">Tjoppen</span>
<span class="nv">Released</span><span class="w"> </span><span class="nv">at</span><span class="w"> </span><span class="nv">Revision</span><span class="w"> </span><span class="mi">2012</span>
<span class="o">-------------------------</span>
<span class="nv">A</span><span class="w"> </span><span class="mi">4</span><span class="nv">k</span><span class="w"> </span><span class="nv">intro</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nv">the</span><span class="w"> </span><span class="nv">Atari</span><span class="w"> </span><span class="mi">2600</span><span class="w"> </span><span class="nv">VCS</span>.
<span class="nv">Features</span><span class="w"> </span><span class="nv">the</span><span class="w"> </span><span class="nv">following</span>:
<span class="o">*</span><span class="w"> </span><span class="nv">Computer</span><span class="w"> </span><span class="nv">screen</span><span class="w"> </span><span class="nv">w</span><span class="o">/</span><span class="w"> </span><span class="nv">power</span><span class="w"> </span><span class="nv">LED</span>
<span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nv">flashing</span>
<span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">6</span><span class="nv">x8</span><span class="w"> </span><span class="nv">character</span><span class="w"> </span><span class="nv">text</span><span class="w"> </span><span class="nv">display</span>
<span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">104</span><span class="w"> </span><span class="nv">color</span><span class="w"> </span><span class="nv">palette</span><span class="w"> </span><span class="nv">demonstrator</span>
<span class="o">*</span><span class="w"> </span><span class="mi">28</span><span class="nv">x18</span><span class="w"> </span><span class="nv">rotozoomer</span>
<span class="o">*</span><span class="w"> </span><span class="nv">Plasma</span><span class="w"> </span><span class="nv">bars</span>
<span class="o">*</span><span class="w"> </span><span class="nv">Much</span><span class="w"> </span><span class="nv">improved</span><span class="w"> </span><span class="mi">2</span><span class="nv">D</span><span class="w"> </span><span class="nv">plasma</span>
<span class="o">*</span><span class="w"> </span><span class="nv">Coder</span><span class="w"> </span><span class="nv">music</span>
<span class="o">*</span><span class="w"> </span><span class="nv">Source</span><span class="w"> </span><span class="nv">code</span>
<span class="k">For</span><span class="w"> </span><span class="nv">my</span><span class="w"> </span><span class="nv">current</span><span class="w"> </span><span class="nv">and</span><span class="w"> </span><span class="nv">future</span><span class="w"> </span><span class="nv">prods</span>,<span class="w"> </span><span class="nv">see</span>
<span class="nv">http</span>:<span class="o">//</span><span class="nv">pouet</span>.<span class="nv">net</span><span class="o">/</span><span class="nv">groups</span>.<span class="nv">php</span>?<span class="nv">which</span><span class="o">=</span><span class="mi">11387</span>
</code></pre></div>plotcube2011-12-17T00:00:00+01:002011-12-17T00:00:00+01:00tomastag:www.härdin.se,2011-12-17:/demoscene/2011/12/17/plotcube/<p>A quick proof-of-concept for point-based 3D on the Atari VCS.
Since then other people have made prods with much better 3D plotters, such as <a href="https://www.pouet.net/prod.php?which=58034">Sphaera Stellarum by noice</a>.</p>Minute and a Bit2011-11-09T00:00:00+01:002011-11-09T00:00:00+01:00tomastag:www.härdin.se,2011-11-09:/demoscene/2011/11/09/minute-and-a-bit/<p>This was my first "proper" demo for the VCS and, in the spirit of oneupmanship,
has the world's first fullscreen plasma for the Atari VCS :)</p>
<p>This prod and <a href="http://www.härdin.se/demoscene/2012/04/08/stella-lives/">Stella Lives!</a> are both included in the Scene Demos 6-in-1 cartridge by SvOlli (<a href="https://www.pouet.net/prod.php?which=61318">pouet.net</a>, <a href="https://demozoo.org/productions/98009/">demozoo.com</a>, <a href="http://xayax.net/nonxayax/scene_demos_6-in-1/">xayax.net</a>).</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="nv">Minute</span><span class="w"> </span><span class="nv">and …</span></code></pre></div><p>This was my first "proper" demo for the VCS and, in the spirit of oneupmanship,
has the world's first fullscreen plasma for the Atari VCS :)</p>
<p>This prod and <a href="http://www.härdin.se/demoscene/2012/04/08/stella-lives/">Stella Lives!</a> are both included in the Scene Demos 6-in-1 cartridge by SvOlli (<a href="https://www.pouet.net/prod.php?which=61318">pouet.net</a>, <a href="https://demozoo.org/productions/98009/">demozoo.com</a>, <a href="http://xayax.net/nonxayax/scene_demos_6-in-1/">xayax.net</a>).</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="nv">Minute</span><span class="w"> </span><span class="nv">and</span><span class="w"> </span><span class="nv">a</span><span class="w"> </span><span class="nv">Bit</span>
<span class="w"> </span><span class="nv">by</span><span class="w"> </span><span class="nv">Tjoppen</span>
<span class="w"> </span><span class="mi">76</span>½<span class="w"> </span><span class="nv">seconds</span><span class="w"> </span><span class="nv">of</span><span class="w"> </span><span class="mi">8</span><span class="nv">k</span><span class="w"> </span><span class="nv">Atari</span><span class="w"> </span><span class="nv">VCS</span><span class="w"> </span><span class="nv">goodness</span>
<span class="w"> </span><span class="nv">Released</span><span class="w"> </span><span class="nv">at</span><span class="w"> </span><span class="nv">Silly</span><span class="w"> </span><span class="nv">Venture</span><span class="w"> </span><span class="mi">2</span><span class="nv">k11</span>
<span class="o">-------------------------------------------------------------------------------</span>
<span class="nv">Featuring</span>:
<span class="o">-</span><span class="w"> </span><span class="nv">Three</span><span class="o">-</span><span class="nv">color</span><span class="w"> </span><span class="nv">twister</span><span class="w"> </span><span class="nv">using</span><span class="w"> </span><span class="nv">M0</span>,<span class="w"> </span><span class="nv">M1</span><span class="w"> </span><span class="nv">and</span><span class="w"> </span><span class="nv">BL</span>
<span class="o">-</span><span class="w"> </span><span class="nv">Two</span><span class="w"> </span><span class="nv">rotozoomers</span>,<span class="w"> </span><span class="nv">neither</span><span class="w"> </span><span class="nv">of</span><span class="w"> </span><span class="nv">them</span><span class="w"> </span><span class="nv">using</span><span class="w"> </span><span class="nv">a</span><span class="w"> </span><span class="nv">frame</span><span class="w"> </span><span class="nv">buffer</span>
<span class="o">-</span><span class="w"> </span><span class="mi">22</span><span class="nv">x114</span><span class="o">-</span><span class="nv">pixel</span><span class="w"> </span><span class="nv">plasma</span>
<span class="o">-</span><span class="w"> </span><span class="nv">Six</span><span class="o">-</span><span class="nv">point</span><span class="w"> </span><span class="nv">rotating</span><span class="w"> </span><span class="nv">two</span><span class="o">-</span><span class="nv">color</span><span class="w"> </span><span class="nv">pinwheel</span><span class="w"> </span><span class="nv">with</span><span class="w"> </span><span class="nv">text</span><span class="w"> </span><span class="nv">greetings</span>
<span class="o">-</span><span class="w"> </span><span class="nv">Coder</span><span class="w"> </span><span class="nv">music</span>,<span class="w"> </span><span class="nv">mostly</span><span class="w"> </span><span class="nv">in</span><span class="w"> </span><span class="nv">tune</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nv">only</span><span class="w"> </span><span class="nv">off</span><span class="w"> </span><span class="nv">by</span><span class="w"> </span><span class="o">~</span><span class="mi">40</span><span class="w"> </span><span class="nv">cents</span><span class="w"> </span><span class="nv">here</span><span class="w"> </span><span class="nv">and</span><span class="w"> </span><span class="nv">there</span>
<span class="o">-</span><span class="w"> </span><span class="nv">Source</span><span class="w"> </span><span class="nv">code</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nv">just</span><span class="w"> </span><span class="nv">copy</span><span class="w"> </span><span class="nv">over</span><span class="w"> </span><span class="nv">DASM</span><span class="err">'s vcs.h and macro.h and make</span>
<span class="nv">This</span><span class="w"> </span><span class="nv">prod</span><span class="w"> </span><span class="nv">uses</span><span class="w"> </span><span class="nv">a</span><span class="w"> </span><span class="nv">modified</span><span class="w"> </span><span class="nv">form</span><span class="w"> </span><span class="nv">of</span><span class="w"> </span><span class="nv">Paul</span><span class="w"> </span><span class="nv">Slocum</span><span class="err">'s Musik Kit 2.0 (finer tempo).</span>
<span class="err">Tools used include DASM, Stella, MESS, a PAL VCS and a Harmony cartridge.</span>
</code></pre></div>Nyantari 26002011-08-15T00:00:00+02:002011-08-15T00:00:00+02:00tomastag:www.härdin.se,2011-08-15:/demoscene/2011/08/15/nyantari-2600/<p>Everyone likes Nyan Cat!</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="nv">Nyantari</span><span class="w"> </span><span class="mi">2600</span>
<span class="o">========================================</span>
<span class="nv">Exactly</span><span class="w"> </span><span class="nv">what</span><span class="w"> </span><span class="nv">it</span><span class="w"> </span><span class="nv">says</span><span class="w"> </span><span class="nv">on</span><span class="w"> </span><span class="nv">the</span><span class="w"> </span><span class="nv">tin</span>:
<span class="nv">Nyan</span><span class="w"> </span><span class="nv">cat</span><span class="w"> </span><span class="nv">on</span><span class="w"> </span><span class="nv">the</span><span class="w"> </span><span class="nv">Atari</span><span class="w"> </span><span class="mi">2600</span><span class="w"> </span><span class="ss">(</span><span class="nv">aka</span><span class="w"> </span><span class="nv">VCS</span><span class="ss">)</span>.
<span class="nv">Released</span><span class="w"> </span><span class="nv">at</span><span class="w"> </span><span class="nv">Evoke</span><span class="w"> </span><span class="mi">2011</span>.
<span class="nv">By</span><span class="w"> </span><span class="nv">Tjoppen</span>.
<span class="nv">History</span>
<span class="o">-------</span>
<span class="nv">This</span><span class="w"> </span><span class="nv">intro</span><span class="w"> </span><span class="nv">was</span><span class="w"> </span><span class="nv">coded</span><span class="w"> </span><span class="nv">in</span><span class="w"> </span><span class="nv">little</span><span class="w"> </span><span class="nv">over</span><span class="w"> </span><span class="nv">one</span><span class="w"> </span><span class="nv">week</span>,
<span class="nv">from</span><span class="w"> </span><span class="nv">Friday</span><span class="w"> </span><span class="nv">at</span><span class="w"> </span><span class="nv">Assembly</span><span class="w"> </span><span class="nv">Summer</span><span class="w"> </span><span class="mi">2011</span><span class="w"> </span><span class="nv">to</span><span class="w"> </span><span class="nv">Saturday</span>
<span class="nv">at</span><span class="w"> </span><span class="nv">Evoke</span><span class="w"> </span><span class="mi">2011</span><span class="w"> </span><span class="ss">(</span><span class="mi">5 …</span></code></pre></div><p>Everyone likes Nyan Cat!</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="nv">Nyantari</span><span class="w"> </span><span class="mi">2600</span>
<span class="o">========================================</span>
<span class="nv">Exactly</span><span class="w"> </span><span class="nv">what</span><span class="w"> </span><span class="nv">it</span><span class="w"> </span><span class="nv">says</span><span class="w"> </span><span class="nv">on</span><span class="w"> </span><span class="nv">the</span><span class="w"> </span><span class="nv">tin</span>:
<span class="nv">Nyan</span><span class="w"> </span><span class="nv">cat</span><span class="w"> </span><span class="nv">on</span><span class="w"> </span><span class="nv">the</span><span class="w"> </span><span class="nv">Atari</span><span class="w"> </span><span class="mi">2600</span><span class="w"> </span><span class="ss">(</span><span class="nv">aka</span><span class="w"> </span><span class="nv">VCS</span><span class="ss">)</span>.
<span class="nv">Released</span><span class="w"> </span><span class="nv">at</span><span class="w"> </span><span class="nv">Evoke</span><span class="w"> </span><span class="mi">2011</span>.
<span class="nv">By</span><span class="w"> </span><span class="nv">Tjoppen</span>.
<span class="nv">History</span>
<span class="o">-------</span>
<span class="nv">This</span><span class="w"> </span><span class="nv">intro</span><span class="w"> </span><span class="nv">was</span><span class="w"> </span><span class="nv">coded</span><span class="w"> </span><span class="nv">in</span><span class="w"> </span><span class="nv">little</span><span class="w"> </span><span class="nv">over</span><span class="w"> </span><span class="nv">one</span><span class="w"> </span><span class="nv">week</span>,
<span class="nv">from</span><span class="w"> </span><span class="nv">Friday</span><span class="w"> </span><span class="nv">at</span><span class="w"> </span><span class="nv">Assembly</span><span class="w"> </span><span class="nv">Summer</span><span class="w"> </span><span class="mi">2011</span><span class="w"> </span><span class="nv">to</span><span class="w"> </span><span class="nv">Saturday</span>
<span class="nv">at</span><span class="w"> </span><span class="nv">Evoke</span><span class="w"> </span><span class="mi">2011</span><span class="w"> </span><span class="ss">(</span><span class="mi">5</span><span class="o">/</span><span class="mi">8</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">13</span><span class="o">/</span><span class="mi">8</span><span class="ss">)</span>.
<span class="nv">Thanks</span>
<span class="o">------</span>
<span class="nv">Paul</span><span class="w"> </span><span class="nv">Slocum</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nv">his</span><span class="w"> </span><span class="nv">excellent</span><span class="w"> </span><span class="nv">music</span><span class="w"> </span><span class="nv">player</span>.
<span class="nv">Brandon</span><span class="w"> </span><span class="nv">Carrita</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nv">transcribing</span><span class="w"> </span><span class="nv">the</span><span class="w"> </span><span class="nv">notes</span>.
<span class="nv">My</span><span class="w"> </span><span class="nv">previous</span><span class="w"> </span><span class="nv">VCS</span><span class="w"> </span><span class="nv">releases</span>
<span class="o">------------------------</span>
<span class="nv">Bell</span><span class="w"> </span><span class="nv">Hopper</span><span class="w"> </span><span class="ss">(</span><span class="nv">a</span><span class="w"> </span><span class="nv">Winterbells</span><span class="w"> </span><span class="nv">demake</span><span class="ss">)</span>
<span class="nv">http</span>:<span class="o">//</span><span class="nv">pouet</span>.<span class="nv">net</span><span class="o">/</span><span class="nv">prod</span>.<span class="nv">php</span>?<span class="nv">which</span><span class="o">=</span><span class="mi">57426</span>
<span class="nv">Contact</span>
<span class="o">-------</span>
<span class="nv">Mail</span>,<span class="w"> </span><span class="nv">slightly</span><span class="w"> </span><span class="nv">obfuscated</span><span class="w"> </span><span class="nv">to</span><span class="w"> </span><span class="nv">avoid</span><span class="w"> </span><span class="nv">spam</span>:
<span class="nv">se</span><span class="w"> </span>.<span class="w"> </span><span class="nv">gamedev</span><span class="w"> </span>@<span class="w"> </span><span class="nv">tjoppen</span>
</code></pre></div>
<p>Note that I have change e-mail since then.</p>Platonic love2011-08-07T23:03:30+02:002011-08-07T23:03:30+02:00tomastag:www.härdin.se,2011-08-07:/demoscene/2011/08/07/platonic-love/<p>Written in C++ and Ogre3D.</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code>Platonic Love - a demo by .fail
Released at Assembly 2011 in Helsinki, Finland
Credits: eczkchtl, funkytune, Tjoppen and zoot
Graphics library: Ogre (http://www.ogre3d.org)
Audio library : FMOD Sound System by Firelight Technologies (http://fmod.org)
</code></pre></div>Bell Hopper2011-08-05T00:00:00+02:002011-08-05T00:00:00+02:00tomastag:www.härdin.se,2011-08-05:/demoscene/2011/08/05/bell-hopper/<p>This was my first foray into coding for the Atari 2600 VCS.
I had previously done some experiments with the NES, but never released anything.
One nice thing about releasing this at Assembly was that everyone in the game compo got free pizza, sauna and beer courtesy of <a href="https://www.rovio.com/">Rovio</a>!</p>
<p>This …</p><p>This was my first foray into coding for the Atari 2600 VCS.
I had previously done some experiments with the NES, but never released anything.
One nice thing about releasing this at Assembly was that everyone in the game compo got free pizza, sauna and beer courtesy of <a href="https://www.rovio.com/">Rovio</a>!</p>
<p>This game also ended up being included in <a href="https://www.atariage.com/store/index.php?l=product_detail&p=1041">The Byte Before Christmas</a> cartridge in 2014.</p>
<h2>.nfo</h2>
<div class="highlight"><pre><span></span><code><span class="n">Bell</span><span class="w"> </span><span class="n">Hopper</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">Atari</span><span class="w"> </span><span class="mi">2600</span>
<span class="k">by</span><span class="w"> </span><span class="n">Tjoppen</span>
<span class="n">Bell</span><span class="w"> </span><span class="n">Hopper</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">demake</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">flash</span><span class="w"> </span><span class="n">game</span><span class="w"> </span><span class="n">Winterbells</span><span class="w"> </span><span class="k">by</span><span class="w"> </span><span class="n">Ferry</span><span class="w"> </span><span class="n">Halim</span><span class="p">.</span>
<span class="n">Jump</span><span class="w"> </span><span class="k">off</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">ground</span><span class="p">,</span><span class="w"> </span><span class="k">then</span><span class="w"> </span><span class="k">go</span><span class="w"> </span><span class="n">higher</span><span class="w"> </span><span class="k">by</span><span class="w"> </span><span class="n">touching</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">bells</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">birds</span><span class="p">.</span>
<span class="n">Score</span><span class="w"> </span><span class="k">by</span><span class="w"> </span><span class="n">touching</span><span class="w"> </span><span class="n">bells</span><span class="p">.</span><span class="w"> </span><span class="n">Touching</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">bird</span><span class="w"> </span><span class="n">will</span><span class="w"> </span><span class="k">double</span><span class="w"> </span><span class="n">your</span><span class="w"> </span><span class="n">existing</span><span class="w"> </span><span class="n">score</span><span class="p">.</span>
<span class="nl">Mail</span><span class="p">:</span><span class="w"> </span><span class="n">se</span><span class="w"> </span><span class="p">.</span><span class="w"> </span><span class="n">gamedev</span><span class="w"> </span><span class="err">@</span><span class="w"> </span><span class="n">tjoppen</span>
</code></pre></div>
<p>Note that I have change e-mail since then.</p>kjempefeil2009-12-06T00:00:00+01:002009-12-06T00:00:00+01:00tomastag:www.härdin.se,2009-12-06:/demoscene/2009/12/06/kjempefeil/<p>Written in C++ and SFML.
The first demo I was involved with that actually got released.</p>